diff --git a/control_plane/trading_studio/cohort_materialization.py b/control_plane/trading_studio/cohort_materialization.py new file mode 100644 index 0000000..60f8e4e --- /dev/null +++ b/control_plane/trading_studio/cohort_materialization.py @@ -0,0 +1,200 @@ +"""Recovery helpers for the frozen HyperScalper Cohort 001 artifact.""" + +from __future__ import annotations + +import csv +import hashlib +import json +from datetime import UTC, datetime +from pathlib import Path +from typing import Any + +DATASET_RECORD_COUNT = 129_599 +FOLD_COUNT = 4 +TRAIN_BARS = 14_400 +EMBARGO_BARS = 35 +TEST_BARS = 7_200 +MANIFEST_HASH_PREFIX = "4d20" +SEMANTIC_DIGEST = "cc697ea359f20ccc83c5d62f5b406a3532c1d7411191423059164aafe5931254" +PROVENANCE = "RECONSTRUCTED_FROM_FROZEN_SPEC_V1" +COHORT_MANIFEST = "cohort_manifest.json" +DATASET_MANIFEST = "dataset_manifest.json" +DATASET_CSV = "binance_btcusdt_spot_2m_180d.csv" + + +def canonical_json(value: Any) -> str: + return json.dumps( + value, + sort_keys=True, + indent=2, + ensure_ascii=True, + default=lambda item: item.isoformat() if isinstance(item, datetime) else str(item), + ) + + +def digest(value: Any) -> str: + return hashlib.sha256(canonical_json(value).encode()).hexdigest() + + +def semantic_digest(members: list[dict[str, Any]]) -> str: + """Hash the prior verifier's ordered, minimal semantic strategy projection.""" + required = ("rank", "source_strategy_id", "base_family", "combo") + if any(not isinstance(member, dict) or set(required) - set(member) for member in members): + raise ValueError("Frozen cohort semantic records are incomplete.") + projection = [ + { + "selection_position": member["rank"], + "source_strategy_id": member["source_strategy_id"], + "base_family": member["base_family"], + "combo": member["combo"], + } + for member in members + ] + positions = [record["selection_position"] for record in projection] + if positions != sorted(positions) or len(set(positions)) != len(positions): + raise ValueError("Frozen cohort semantic records are not uniquely ordered.") + payload = json.dumps(projection, sort_keys=True, ensure_ascii=True, separators=(",", ":")) + return hashlib.sha256(payload.encode()).hexdigest() + + +def file_digest(path: Path) -> str: + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def validate_manifest(manifest: dict[str, Any], *, cohort: bool = False) -> None: + """Validate the frozen manifest's canonical self hash and declared semantics.""" + hash_key = "manifest_sha256" if "manifest_sha256" in manifest else "sha256" + stored = manifest.get(hash_key) + actual = digest({key: value for key, value in manifest.items() if key != hash_key}) + if not isinstance(stored, str) or stored != actual: + raise ValueError("Frozen manifest canonical hash does not verify.") + if cohort and not stored.startswith(MANIFEST_HASH_PREFIX): + raise ValueError("Frozen cohort manifest is not the required 4d20 canonical manifest.") + if cohort: + members = manifest.get("members") + if not isinstance(members, list): + raise ValueError("Frozen cohort manifest is missing ordered strategy records.") + if semantic_digest(members) != SEMANTIC_DIGEST: + raise ValueError("Frozen cohort semantic digest does not verify.") + lineage = manifest.get("lineage") + if lineage is not None and manifest.get("lineage_sha256") != digest(lineage): + raise ValueError("Frozen manifest lineage hash does not verify.") + + +def validate_dataset_manifest(manifest: dict[str, Any]) -> None: + """Validate dataset declarations; its sha256 is the CSV artifact hash, not a self-hash.""" + required = ("artifact", "sha256", "row_count", "fields", "monotonic_timestamps", "schema_valid") + if any(key not in manifest for key in required): + raise ValueError("Dataset manifest is missing required artifact declarations.") + if ( + not isinstance(manifest["artifact"], str) + or not isinstance(manifest["sha256"], str) + or len(manifest["sha256"]) != 64 + or manifest["row_count"] != DATASET_RECORD_COUNT + or not isinstance(manifest["fields"], list) + or not manifest["monotonic_timestamps"] + or not manifest["schema_valid"] + ): + raise ValueError("Dataset manifest declarations are invalid.") + + +def validate_selection_source( + cohort_manifest: dict[str, Any], selection: dict[str, Any], supplied_path: Path +) -> str: + """Bind the unhashed declared source report to all 20 frozen member records.""" + if cohort_manifest.get("source_report") != str(supplied_path): + raise ValueError("Supplied selection source does not match cohort source_report.") + selected = selection.get("selected") + members = cohort_manifest.get("members") + if not isinstance(selected, list) or not isinstance(members, list) or len(members) != 20: + raise ValueError("Selection source or frozen members are incomplete.") + for member, source in zip(members, selected[:20], strict=True): + if ( + not isinstance(source, dict) + or source.get("selection") != member.get("old_selection_metrics") + or source.get("final") != member.get("old_final_metrics") + or source.get("selection", {}).get("id") != member.get("source_strategy_id") + or source.get("selection", {}).get("name") != member.get("source_name") + ): + raise ValueError("Selection source does not reproduce the frozen member order.") + return file_digest(supplied_path) + + +def _timestamp(value: str) -> datetime: + raw = float(value) + if raw > 100_000_000_000: + raw /= 1_000 + return datetime.fromtimestamp(raw, tz=UTC) + + +def load_csv(path: Path, timestamp_field: str) -> tuple[list[dict[str, Any]], list[str]]: + with path.open(newline="", encoding="utf-8") as handle: + reader = csv.DictReader(handle) + headers = reader.fieldnames or [] + if timestamp_field not in headers: + raise ValueError(f"Dataset CSV is missing timestamp field {timestamp_field!r}.") + rows = [] + for raw in reader: + row: dict[str, Any] = dict(raw) + row[timestamp_field] = _timestamp(raw[timestamp_field]) + for field in ("open", "high", "low", "close", "volume"): + if field in row: + row[field] = float(row[field]) + rows.append(row) + return rows, headers + + +def validate_rows(rows: list[dict[str, Any]], headers: list[str], manifest: dict[str, Any]) -> None: + if len(rows) != DATASET_RECORD_COUNT: + raise ValueError(f"Cohort001 requires exactly {DATASET_RECORD_COUNT} bars.") + expected_headers = manifest.get( + "fields", manifest.get("columns", manifest.get("schema", manifest.get("dataset_schema"))) + ) + if isinstance(expected_headers, dict): + expected_headers = list(expected_headers) + if expected_headers != headers: + raise ValueError("Dataset CSV schema differs from the frozen dataset manifest.") + timestamp_field = manifest.get("timestamp_field", "timestamp") + timestamps = [row[timestamp_field] for row in rows] + interval = timestamps[1] - timestamps[0] + if interval.total_seconds() <= 0 or any( + right - left != interval for left, right in zip(timestamps, timestamps[1:], strict=False) + ): + raise ValueError("Dataset timestamp continuity does not verify.") + canonical_rows = [ + { + key: value.isoformat() if isinstance(value, datetime) else value + for key, value in row.items() + } + for row in rows + ] + expected = manifest.get("canonical_rows_sha256") + if expected is not None and expected != digest(canonical_rows): + raise ValueError("Dataset canonical row hash does not verify.") + + +def reconstruct_folds(rows: list[dict[str, Any]], timestamp_field: str) -> list[dict[str, Any]]: + block = TRAIN_BARS + EMBARGO_BARS + TEST_BARS + starts = [index * (len(rows) - block) // (FOLD_COUNT - 1) for index in range(FOLD_COUNT)] + folds = [] + for number, start in enumerate(starts, start=1): + train_end = start + TRAIN_BARS + test_start = train_end + EMBARGO_BARS + test_end = test_start + TEST_BARS + fold = {"fold": f"Fold {number}", "provenance": PROVENANCE} + for name, begin, end in ( + ("train", start, train_end), + ("embargo", train_end, test_start), + ("test", test_start, test_end), + ): + fold[name] = { + "start_index": begin, + "end_index": end - 1, + "bars": end - begin, + "start_at": rows[begin][timestamp_field].isoformat(), + "end_at": rows[end - 1][timestamp_field].isoformat(), + "sha256": digest(rows[begin:end]), + "status": "EXCLUDED" if name == "embargo" else "ACTIVE", + } + folds.append(fold) + return folds diff --git a/control_plane/trading_studio/indicators/__init__.py b/control_plane/trading_studio/indicators/__init__.py new file mode 100644 index 0000000..088484a --- /dev/null +++ b/control_plane/trading_studio/indicators/__init__.py @@ -0,0 +1,44 @@ +"""Versioned indicator registry contracts. Formula implementations are deliberately absent.""" + +from .engine import ( + IndicatorEngine, + RefusalCode, + RefusalState, + compute_hs22_state, + evaluate_indicator, +) +from .feature_catalog import ( + FEATURE_CATALOG_V1, + CausalClassification, + FeatureResearchDefinition, + FeatureSupportState, + require_validated_features, +) +from .registry import ( + HISTORICAL_REGISTRY, + HS22_COHORT001_V1, + HS22_HISTORICAL_COMPLETE_V1, + HS22_REQUIRED_V1, + historical_artifact_digest, +) +from .schema import HS22State, parse_hs22 + +__all__ = [ + "HISTORICAL_REGISTRY", + "HS22_COHORT001_V1", + "HS22_REQUIRED_V1", + "HS22_HISTORICAL_COMPLETE_V1", + "FEATURE_CATALOG_V1", + "CausalClassification", + "FeatureResearchDefinition", + "FeatureSupportState", + "HS22State", + "IndicatorEngine", + "RefusalCode", + "RefusalState", + "historical_artifact_digest", + "compute_hs22_state", + "evaluate_indicator", + "parse_hs22", + "require_validated_features", +] diff --git a/control_plane/trading_studio/indicators/batch01_native_parity.py b/control_plane/trading_studio/indicators/batch01_native_parity.py new file mode 100644 index 0000000..45062d1 --- /dev/null +++ b/control_plane/trading_studio/indicators/batch01_native_parity.py @@ -0,0 +1,307 @@ +"""Offline exact-parity gate for the frozen Batch01 band/channel oracle.""" + +from __future__ import annotations + +import csv +import hashlib +import json +from pathlib import Path +from typing import Any + +import numpy as np + +from .historical_band_channel import OBSERVED_BAND_CHANNEL_PARAMS, evaluate_band_channel +from .parity_harness_v1 import ( + ComparisonRecord, + FeatureVersion, + ParityStatus, + compare_array, + compare_float64_ulp, + recompute_coverage, +) + +ROOT = Path(__file__).resolve().parents[3] +BATCH01_REQUEST = ROOT / "batch01_oracle_request.json" +BATCH01_RESULT = ROOT / "batch01_oracle_result.json" +BATCH01_OUTPUTS = ROOT / "batch01_oracle_outputs.npz" +CANONICAL_CSV = ROOT / "hs22_oracle_v1" / "binance_btcusdt_spot_2m_180d.csv" +BOLLINGER_RESOLUTION = ROOT / "batch01_bollinger_parity_resolution_v1.json" +BOLLINGER_ROOT_REPORT = ROOT / "batch01_native_mismatch_report.json" + +_DIGESTS = { + "batch01_oracle_request.json": ( + "7ca0c8578dd81c3ae60898d83e6e73f9bf8889a39a873b451c7cdaf036cbaf24" + ), + "batch01_oracle_result.json": ( + "7c1d5dbdcb183aa2d872baa45c4d02fe2d59cccabe9022f8797237b3776c8e96" + ), + "batch01_oracle_outputs.npz": ( + "e1f2268b634e50eb65b9b5175ea369e52bf0a2039b18049030849948a45fd149" + ), + "hs22_oracle_v1/binance_btcusdt_spot_2m_180d.csv": ( + "7fb56bb05b0edc2348407765cd693efadf334307c25877dfb52acfe4221e5d00" + ), +} + + +class FrozenBatch01ArtifactError(ValueError): + """Raised when a parity input is not the pinned local oracle artifact.""" + + +def _digest(path: Path) -> str: + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def _canonical_bytes(value: object) -> bytes: + return json.dumps(value, sort_keys=True, separators=(",", ":"), allow_nan=False).encode("utf-8") + + +def _array_digest(values: np.ndarray) -> str: + values = np.ascontiguousarray(values) + header = _canonical_bytes({"dtype": values.dtype.str, "shape": values.shape}) + return hashlib.sha256(header + b"\0" + values.tobytes()).hexdigest() + + +def batch01_native_parity_manifest() -> dict[str, object]: + """Return the reproducible exact-comparison contract for all 97 variants.""" + return { + "schema_version": 1, + "artifact": "BATCH01_NATIVE_PARITY_MANIFEST_V1", + "engine_revision": "code-5056feb", + "frozen_inputs": { + name: {"path": name, "sha256": digest} for name, digest in _DIGESTS.items() + }, + "input_columns": ["close", "high", "low", "volume"], + "variant_count": 97, + "comparison": {"dtype": "exact", "shape": "exact", "nan_mask": "exact", "values": "exact"}, + "documented_exception": { + "path": BOLLINGER_RESOLUTION.name, + "scope": "float64 one-ULP cases listed for indicator IDs 17 and 18 only", + "global_tolerance": "forbidden", + }, + "derived_state_transitions": { + "indicator_ids": [19, 28], + "state": "1 when close is greater than output, otherwise -1; warmup NaN is 0", + "transitions": "state differs from the preceding bar", + }, + } + + +def batch01_native_parity_manifest_bytes() -> bytes: + return _canonical_bytes(batch01_native_parity_manifest()) + b"\n" + + +def write_batch01_native_parity_manifest(path: Path) -> None: + path.write_bytes(batch01_native_parity_manifest_bytes()) + + +def _require_frozen_artifacts() -> tuple[dict[str, Any], dict[str, Any]]: + paths = { + "batch01_oracle_request.json": BATCH01_REQUEST, + "batch01_oracle_result.json": BATCH01_RESULT, + "batch01_oracle_outputs.npz": BATCH01_OUTPUTS, + "hs22_oracle_v1/binance_btcusdt_spot_2m_180d.csv": CANONICAL_CSV, + } + for name, path in paths.items(): + if _digest(path) != _DIGESTS[name]: + raise FrozenBatch01ArtifactError(f"{name} digest does not match the frozen artifact") + request = json.loads(BATCH01_REQUEST.read_text(encoding="utf-8")) + result = json.loads(BATCH01_RESULT.read_text(encoding="utf-8")) + if request.get("artifact") != "HISTORICAL_FEATURE_ORACLE_V1_REQUEST": + raise FrozenBatch01ArtifactError("invalid Batch01 request artifact") + if result.get("artifact") != "HISTORICAL_FEATURE_ORACLE_V1_RESULT": + raise FrozenBatch01ArtifactError("invalid Batch01 result artifact") + if result.get("request_sha256") != _DIGESTS["batch01_oracle_request.json"]: + raise FrozenBatch01ArtifactError("result is not linked to the frozen request") + csv_digest = _DIGESTS["hs22_oracle_v1/binance_btcusdt_spot_2m_180d.csv"] + if result.get("input_csv_sha256") != csv_digest: + raise FrozenBatch01ArtifactError("result is not linked to the canonical CSV") + if result.get("outputs_npz", {}).get("sha256") != _DIGESTS["batch01_oracle_outputs.npz"]: + raise FrozenBatch01ArtifactError("result is not linked to the frozen NPZ") + return request, result + + +def _bollinger_resolution() -> dict[str, tuple[dict[str, Any], ...]]: + resolution = json.loads(BOLLINGER_RESOLUTION.read_text(encoding="utf-8")) + report = json.loads(BOLLINGER_ROOT_REPORT.read_text(encoding="utf-8")) + source = resolution.get("source_report", {}) + exception = resolution.get("exception", {}) + if ( + resolution.get("artifact") != "BATCH01_BOLLINGER_PARITY_RESOLUTION_V1" + or resolution.get("schema_version") != 1 + or source.get("artifact") != report.get("artifact") + or source.get("classification") != report.get("classification") + or source.get("failed_value_count") != report.get("failed_value_count") + or exception != { + "indicator_ids": [17, 18], + "dtype": "float64", + "max_ulps": 1, + "unlisted_mismatch_policy": "fail", + "all_other_indicators_policy": "exact", + "shape_policy": "exact", + "nan_mask_policy": "exact", + } + ): + raise FrozenBatch01ArtifactError("invalid Bollinger parity resolution") + report_cases = { + (item["request_id"], int(detail["index"])): { + "indicator_id": item["indicator_id"], + "signed_ulp": detail["ulp"]["signed"], + "threshold_sensitivity": { + key: detail["threshold_sensitivity"][key] + for key in ( + "oracle_close_above_band", + "native_close_above_band", + "decision_changed", + "close_to_oracle_band_ulps", + "close_to_native_band_ulps", + ) + }, + } + for item in report["variants"] + for detail in item["mismatches"] + } + accepted = resolution.get("accepted_cases") + if not isinstance(accepted, list) or len(accepted) != 8: + raise FrozenBatch01ArtifactError("resolution must list all eight accepted cases") + resolution_cases = { + (item["request_id"], int(item["index"])): { + "indicator_id": item["indicator_id"], + "signed_ulp": item["signed_ulp"], + "threshold_sensitivity": item["threshold_sensitivity"], + } + for item in accepted + } + if resolution_cases != report_cases or any( + int(item["indicator_id"]) not in {17, 18} + or item["threshold_sensitivity"]["decision_changed"] + for item in accepted + ): + raise FrozenBatch01ArtifactError("resolution does not match the root-cause evidence") + grouped: dict[str, list[dict[str, Any]]] = {} + for item in accepted: + grouped.setdefault(item["request_id"], []).append(item) + return {request_id: tuple(cases) for request_id, cases in grouped.items()} + + +def _load_ohlcv() -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: + with CANONICAL_CSV.open(newline="", encoding="utf-8") as handle: + rows = list(csv.DictReader(handle)) + return tuple( + np.asarray([float(row[name]) for row in rows], dtype=np.float64) + for name in ("close", "high", "low", "volume") + ) # type: ignore[return-value] + + +def _state_and_transitions(close: np.ndarray, output: np.ndarray) -> tuple[np.ndarray, np.ndarray]: + state = np.zeros(output.shape, dtype=np.int8) + valid = ~np.isnan(output) + state[valid] = np.where(close[valid] > output[valid], 1, -1) + transitions = np.zeros(output.shape, dtype=np.bool_) + transitions[1:] = state[1:] != state[:-1] + return state, transitions + + +def _record_artifact(record: ComparisonRecord) -> dict[str, object]: + return record.artifact() + + +def batch01_native_acceptance_manifest(report: dict[str, object]) -> dict[str, object]: + """Summarize the resolved Batch01 gate and recompute its submitted coverage.""" + variants = [item for item in report["records"] if ":" not in item["name"]] + feature_versions = [ + FeatureVersion( + feature_version=item["name"], + primitive_key=item["name"], + engineering_family="band_channel", + usage_slots=1, + status=ParityStatus(item["status"]), + ) + for item in variants + ] + accepted = [ + item for item in variants if item["reason"] == "accepted_documented_float64_ulp_drift" + ] + return { + "schema_version": 1, + "artifact": "BATCH01_NATIVE_ACCEPTANCE_MANIFEST_V1", + "parity_manifest": batch01_native_parity_manifest(), + "status": "accepted" if report["passed"] else "rejected", + "accepted_documented_ulp_variant_count": len(accepted), + "accepted_documented_ulp_value_count": sum(item["value_mismatches"] for item in accepted), + "coverage": recompute_coverage(feature_versions), + } + + +def write_batch01_native_acceptance_manifest(path: Path) -> None: + report = evaluate_batch01_native_parity() + path.write_bytes(_canonical_bytes(batch01_native_acceptance_manifest(report)) + b"\n") + + +def evaluate_batch01_native_parity() -> dict[str, object]: + """Evaluate native Batch01 functions against the immutable oracle NPZ exactly.""" + request, result = _require_frozen_artifacts() + accepted_cases = _bollinger_resolution() + requests = request["requests"] + result_requests = {item["request_id"]: item for item in result["requests"]} + requested_params = { + (int(item["indicator_id"]), int(item["period"]), float(item["p1"])) for item in requests + } + if requested_params != OBSERVED_BAND_CHANNEL_PARAMS or len(requests) != 97: + raise FrozenBatch01ArtifactError("request variants do not match the Batch01 native surface") + if set(result_requests) != {item["request_id"] for item in requests}: + raise FrozenBatch01ArtifactError("result request records do not match the frozen request") + close, high, low, volume = _load_ohlcv() + records: list[ComparisonRecord] = [] + with np.load(BATCH01_OUTPUTS) as expected_outputs: + if set(expected_outputs.files) != set(result_requests): + raise FrozenBatch01ArtifactError("NPZ output keys do not match result request records") + for item in requests: + request_id = item["request_id"] + expected = expected_outputs[request_id] + metadata = result_requests[request_id] + if expected.dtype.str != metadata["dtype"] or list(expected.shape) != metadata["shape"]: + raise FrozenBatch01ArtifactError(f"NPZ metadata mismatch for {request_id}") + if _array_digest(expected) != metadata["sha256"]: + raise FrozenBatch01ArtifactError(f"NPZ value digest mismatch for {request_id}") + actual = evaluate_band_channel( + int(item["indicator_id"]), + close, + high, + low, + volume, + int(item["period"]), + float(item["p1"]), + ) + indicator_id = int(item["indicator_id"]) + cases = accepted_cases.get(request_id, ()) + records.append( + compare_float64_ulp( + request_id, + expected, + actual, + max_ulps=1, + allowed_indexes=frozenset(int(case["index"]) for case in cases), + ) + if indicator_id in {17, 18} + else compare_array(request_id, expected, actual) + ) + if indicator_id in {19, 28}: + expected_state, expected_transitions = _state_and_transitions(close, expected) + actual_state, actual_transitions = _state_and_transitions(close, actual) + records.append(compare_array(f"{request_id}:state", expected_state, actual_state)) + records.append( + compare_array( + f"{request_id}:transitions", expected_transitions, actual_transitions + ) + ) + failures = [record for record in records if not record.passed] + report = { + "manifest": batch01_native_parity_manifest(), + "records": [_record_artifact(record) for record in records], + "passed": not failures, + "failure_count": len(failures), + "failures": [_record_artifact(record) for record in failures], + } + report["acceptance_manifest"] = batch01_native_acceptance_manifest(report) + return report diff --git a/control_plane/trading_studio/indicators/batch01_oracle_manifest.py b/control_plane/trading_studio/indicators/batch01_oracle_manifest.py new file mode 100644 index 0000000..aa24636 --- /dev/null +++ b/control_plane/trading_studio/indicators/batch01_oracle_manifest.py @@ -0,0 +1,65 @@ +"""Deterministic external-oracle requests for the observed Batch01 surface.""" + +from __future__ import annotations + +import hashlib +import json +from pathlib import Path + +from .historical_band_channel import OBSERVED_BAND_CHANNEL_PARAMS + +BATCH01_ORACLE_REQUEST_MANIFEST_V1_PATH = Path(__file__).with_name( + "batch01_oracle_request_manifest_v1.json" +) +_ENGINE_REVISION = "code-5056feb" +_SEMANTIC_FIELDS = { + "engine_revision": _ENGINE_REVISION, + "input_columns": ["close", "high", "low", "volume"], + "output_dtype": "float64", + "window_policy": "continuous_full_history", +} + + +def _canonical_bytes(value: object) -> bytes: + return json.dumps(value, sort_keys=True, separators=(",", ":"), allow_nan=False).encode("utf-8") + + +def batch01_oracle_request_manifest() -> dict[str, object]: + """Build exact observed requests without evaluating any historical formula.""" + requests = [] + for indicator_id, period, p1 in sorted(OBSERVED_BAND_CHANNEL_PARAMS): + semantic = { + **_SEMANTIC_FIELDS, + "indicator_id": indicator_id, + "period": period, + "p1": p1, + } + requests.append( + { + "request_id": f"batch01_{indicator_id}_{period}_{p1:g}", + "indicator_id": indicator_id, + "period": period, + "p1": p1, + "semantic_fingerprint": hashlib.sha256(_canonical_bytes(semantic)).hexdigest(), + } + ) + assert len(requests) == 97 + return { + "schema_version": 1, + "artifact": "HISTORICAL_FEATURE_ORACLE_V1_REQUEST", + "engine_revision": _ENGINE_REVISION, + "input_columns": _SEMANTIC_FIELDS["input_columns"], + "output_dtype": _SEMANTIC_FIELDS["output_dtype"], + "window_policy": _SEMANTIC_FIELDS["window_policy"], + "requests": requests, + } + + +def batch01_oracle_request_manifest_bytes() -> bytes: + return _canonical_bytes(batch01_oracle_request_manifest()) + b"\n" + + +def write_batch01_oracle_request_manifest( + path: Path = BATCH01_ORACLE_REQUEST_MANIFEST_V1_PATH, +) -> None: + path.write_bytes(batch01_oracle_request_manifest_bytes()) diff --git a/control_plane/trading_studio/indicators/definitions.py b/control_plane/trading_studio/indicators/definitions.py new file mode 100644 index 0000000..f9d22ec --- /dev/null +++ b/control_plane/trading_studio/indicators/definitions.py @@ -0,0 +1,264 @@ +"""Typed, data-only definitions for the recovered HS22 indicator inventory.""" + +from __future__ import annotations + +from dataclasses import asdict, dataclass +from enum import StrEnum +from itertools import product + + +class Role(StrEnum): + LEVEL = "level" + OSC = "osc" + TREND = "trend" + FILTER = "filter" + + +class ImplementationStatus(StrEnum): + UNIMPLEMENTED = "unimplemented" + ALIAS = "alias" + UNREGISTERED = "unregistered" + + +@dataclass(frozen=True, slots=True) +class IndicatorDefinition: + indicator_id: int + name: str + role: Role | None + status: ImplementationStatus = ImplementationStatus.UNIMPLEMENTED + alias_of: int | None = None + behavior: str = "refuse_execution" + + +@dataclass(frozen=True, slots=True) +class IndicatorVariant: + indicator_id: int + period: int + p1: float + role: Role + + def asdict(self) -> dict[str, object]: + return asdict(self) + + +# Recovered from the historical pool definition. This is deliberately data, not +# a dependency on or import of the reference runtime. +_SPECS: tuple[tuple[int, str, Role, tuple[int, ...], tuple[float, ...]], ...] = ( + *( + (i, name, Role.LEVEL, tuple(range(start, stop, step)), params) + for i, name, start, stop, step, params in ( + (0, "SMA", 5, 51, 3, (0.0,)), + (1, "EMA", 5, 51, 3, (0.0,)), + (2, "WMA", 5, 51, 3, (0.0,)), + (3, "HMA", 6, 51, 2, (0.0,)), + (4, "DEMA", 5, 41, 3, (0.0,)), + (5, "TEMA", 5, 36, 3, (0.0,)), + (6, "KAMA", 8, 36, 3, (0.0,)), + (7, "EHLERS_SS", 6, 31, 2, (0.0,)), + (8, "MCGINLEY", 8, 36, 3, (0.0,)), + (9, "JMA", 8, 36, 4, (-50.0, 0.0, 50.0, 100.0)), + (10, "T3", 8, 31, 3, (0.6, 0.7, 0.8, 0.9)), + (11, "ALMA", 8, 31, 3, (4.0, 6.0, 8.0)), + (12, "ZLEMA", 5, 41, 3, (0.0,)), + (13, "VIDYA", 8, 36, 4, (0.0,)), + (14, "FRAMA", 10, 41, 4, (0.0,)), + (15, "LSMA", 8, 41, 3, (0.0,)), + (16, "SWMA", 5, 31, 3, (0.0,)), + (17, "BB_UPPER", 14, 26, 2, (1.5, 2.0, 2.5)), + (18, "BB_LOWER", 14, 26, 2, (1.5, 2.0, 2.5)), + (19, "SUPERTREND", 8, 16, 2, (2.0, 3.0, 4.0)), + (20, "DONCHIAN_UPPER", 10, 30, 4, (0.0,)), + (21, "DONCHIAN_LOWER", 10, 30, 4, (0.0,)), + (22, "DONCHIAN_MID", 10, 30, 4, (0.0,)), + (23, "KELTNER_UPPER", 14, 26, 2, (1.0, 1.5, 2.0)), + (24, "KELTNER_LOWER", 14, 26, 2, (1.0, 1.5, 2.0)), + ) + ), + (25, "KELTNER_MID", Role.LEVEL, tuple(range(14, 26, 2)), (0.0,)), + (26, "ICHIMOKU_TENKAN", Role.LEVEL, tuple(range(7, 13, 2)), (0.0,)), + (27, "ICHIMOKU_KIJUN", Role.LEVEL, tuple(range(20, 30, 2)), (0.0,)), + (28, "PSAR", Role.LEVEL, (1,), (0.01, 0.02, 0.03)), +) + +# The remaining recovered records use compact rows: id, name, role, periods, p1 values. +_COMPACT_SPECS = ( + (30, "RSI", "osc", range(6, 28, 2)), + (31, "STOCH_K", "osc", range(5, 22, 2)), + (32, "STOCH_D", "osc", range(5, 22, 2)), + (33, "CCI", "osc", range(10, 30, 2)), + (34, "WILLIAMS_R", "osc", range(5, 22, 2)), + (35, "ROC", "osc", range(5, 21, 2)), + (36, "CMO", "osc", range(8, 22, 2)), + (37, "TRIX", "osc", range(8, 22, 2)), + (38, "PPO", "osc", range(16, 30, 2)), + (39, "MACD_HIST", "osc", range(20, 32, 2)), + (40, "MFI", "osc", range(10, 22, 2)), + (41, "DPO", "osc", range(10, 26, 2)), + (42, "PCTILE_RANK", "osc", range(14, 51, 6)), + (43, "ZSCORE", "osc", range(14, 51, 6)), + (44, "MINMAX", "osc", range(14, 51, 6)), + *( + (i, name, "osc", periods) + for i, name, periods in ( + (90, "MICRO_BODY_RATIO", range(5, 21, 3)), + (91, "MICRO_UPPER_WICK", range(5, 21, 3)), + (92, "MICRO_LOWER_WICK", range(5, 21, 3)), + (93, "MICRO_BUY_PRESSURE", range(5, 21, 3)), + (94, "MICRO_SELL_PRESSURE", range(5, 21, 3)), + (95, "MICRO_STOP_HUNT", range(10, 21, 5)), + (96, "MICRO_FVG", (1,)), + (97, "MICRO_LIQ_SWEEP", range(5, 21, 4)), + (98, "TREND_BREAKOUT", range(10, 31, 5)), + (99, "TREND_PULLBACK", range(10, 31, 5)), + (100, "MOM_VELOCITY", range(5, 21, 3)), + (101, "MOM_ACCELERATION", range(5, 21, 3)), + (102, "MOM_COMPOSITE", range(12, 31, 4)), + (103, "MOM_NORMALIZED_ROC", range(5, 21, 3)), + (104, "CROSS_PRICE_VS_EMA", range(8, 31, 3)), + (105, "CROSS_EMA_SPREAD", range(14, 41, 4)), + (106, "CROSS_MOM_X_VOL", range(8, 21, 3)), + (107, "CROSS_VOL_ADJ_MOM", range(8, 21, 3)), + (108, "NORM_RETURN_ZSCORE", range(14, 51, 6)), + (109, "TIME_BARS_SINCE_HIGH", range(10, 51, 10)), + (110, "TIME_BARS_SINCE_LOW", range(10, 51, 10)), + (116, "REGIME_SKEWNESS", range(20, 61, 10)), + (52, "VOL_ATR_ZSCORE", range(10, 31, 5)), + (59, "VOL_RANGE_PCTILE", range(14, 31, 4)), + (60, "VOL_TR_MOMENTUM", range(10, 31, 5)), + ) + ), + *( + (i, name, "trend", periods) + for i, name, periods in ( + (70, "ADX", range(10, 22, 2)), + (71, "AROON_UP", range(10, 30, 4)), + (72, "AROON_DOWN", range(10, 30, 4)), + (73, "LINREG_SLOPE", range(8, 31, 3)), + (74, "LINREG_R2", range(8, 31, 3)), + (75, "EFFICIENCY", range(8, 31, 3)), + (76, "ANGLE", range(8, 31, 3)), + (77, "DURATION", (1,)), + (78, "HURST", range(20, 61, 10)), + (80, "FRACTAL_DIM", range(20, 61, 10)), + (81, "TREND_PERSIST", range(10, 31, 5)), + (83, "MICRO_TREND_STRUCT", range(5, 21, 3)), + ) + ), +) + + +def _variants() -> tuple[IndicatorVariant, ...]: + specs = list(_SPECS) + specs.extend((i, n, Role(r), tuple(p), (0.0,)) for i, n, r, p in _COMPACT_SPECS) + specs.extend( + ( + (79, "VARIANCE_RATIO", Role.TREND, tuple(range(20, 61, 10)), (2.0, 4.0, 8.0)), + (82, "AUTOCORR", Role.TREND, tuple(range(20, 51, 10)), (1.0, 3.0, 5.0)), + ) + ) + specs.extend( + (i, n, Role.FILTER, tuple(p), (0.0,)) + for i, n, p in ( + (50, "ATR", range(8, 22, 2)), + (51, "ATR_PCT", range(8, 22, 2)), + (53, "VOL_COMPRESSION", range(14, 31, 4)), + (54, "VOL_OF_VOL", range(14, 31, 4)), + (55, "VOL_PARKINSON", range(10, 31, 5)), + (56, "VOL_GARMAN_KLASS", range(10, 31, 5)), + (57, "VOL_ROGERS_SATCHELL", range(10, 31, 5)), + (58, "VOL_REALIZED", range(10, 31, 5)), + (61, "NORM_VOL_ZSCORE", range(14, 51, 6)), + (63, "MICRO_VOL_DELTA", range(5, 21, 3)), + (111, "ENTROPY_SHANNON", range(20, 61, 10)), + (112, "KURTOSIS", range(20, 61, 10)), + (113, "HALFLIFE", range(30, 61, 10)), + (115, "MA_COMPRESSION", range(10, 31, 5)), + (118, "TIME_HOUR_COS", (1,)), + (119, "TIME_SESSION_VOL", (1,)), + ) + ) + specs.extend( + ( + (62, "MICRO_VOL_CLUSTERING", Role.TREND, tuple(range(10, 31, 5)), (0.0,)), + (117, "TIME_HOUR_SIN", Role.TREND, (1,), (0.0,)), + ) + ) + specs.append((114, "DC_EVENTS", Role.FILTER, tuple(range(20, 51, 10)), (10.0, 20.0, 50.0))) + specs.extend( + ( + i, + n, + Role.LEVEL if role == "level" else Role.OSC if role == "osc" else Role.FILTER, + tuple(p), + params, + ) + for i, n, role, p, params in ( + (120, "PIVOT_CLASSIC", "level", range(30, 361, 30), (0.0,)), + (121, "PIVOT_R1", "level", range(30, 361, 30), (0.0,)), + (122, "PIVOT_S1", "level", range(30, 361, 30), (0.0,)), + (123, "PIVOT_DISTANCE", "osc", range(30, 361, 30), (0.0,)), + (124, "PREV_PERIOD_HIGH", "level", range(30, 361, 30), (0.0,)), + (125, "PREV_PERIOD_LOW", "level", range(30, 361, 30), (0.0,)), + (126, "PREV_PERIOD_CLOSE", "level", range(30, 361, 30), (0.0,)), + (127, "ROLLING_MEDIAN", "level", range(10, 41, 5), (0.0,)), + (128, "LINREG_CHAN_UPPER", "level", range(14, 31, 4), (1.5, 2.0, 2.5)), + (129, "LINREG_CHAN_LOWER", "level", range(14, 31, 4), (1.5, 2.0, 2.5)), + (130, "QUANTILE_UPPER", "level", range(14, 41, 6), (0.0,)), + (131, "QUANTILE_LOWER", "level", range(14, 41, 6), (0.0,)), + (135, "FRESH_BREAKOUT", "osc", range(10, 31, 5), (0.0,)), + (136, "FAILED_BREAKOUT", "osc", range(10, 31, 5), (0.0,)), + (137, "FIRST_PULLBACK", "osc", range(10, 31, 5), (0.0,)), + (138, "VOL_EXPANSION", "osc", range(10, 21, 5), (0.0,)), + (139, "INSIDE_BAR", "osc", (1,), (0.0,)), + (140, "COMPRESS_RELEASE", "osc", range(10, 21, 5), (0.0,)), + (141, "SWEEP_RECLAIM", "osc", range(10, 31, 5), (0.0,)), + (142, "CLOSE_IN_RANGE", "osc", (1,), (0.0,)), + (143, "CLOSE_IN_ROLLING_RANGE", "osc", range(10, 31, 5), (0.0,)), + (144, "DIST_RECENT_HIGH", "osc", range(10, 31, 5), (0.0,)), + (145, "DIST_RECENT_LOW", "osc", range(10, 31, 5), (0.0,)), + (146, "CHANNEL_POSITION", "osc", range(14, 31, 4), (0.0,)), + (147, "OC_VS_PRIOR", "osc", range(10, 31, 5), (0.0,)), + (150, "CHOP_INDEX", "filter", range(10, 31, 5), (0.0,)), + (151, "CANDLE_OVERLAP", "filter", range(10, 31, 5), (0.0,)), + (152, "NOISE_RATIO", "filter", range(10, 31, 5), (0.0,)), + (153, "WICK_INSTABILITY", "filter", range(10, 31, 5), (0.0,)), + (154, "FALSE_BREAK_FREQ", "filter", range(10, 31, 10), (0.0,)), + (155, "SPREAD_PROXY", "filter", range(10, 31, 5), (0.0,)), + (156, "DIR_CLEAN", "filter", range(10, 31, 5), (0.0,)), + (157, "REVERSAL_FREQ", "filter", range(10, 31, 5), (0.0,)), + (158, "MEDIAN_EXCURSION", "filter", range(10, 31, 5), (0.0,)), + (160, "RSI_SLOPE", "osc", range(8, 22, 2), (0.0,)), + (161, "RSI_DIST_50", "osc", range(8, 22, 2), (0.0,)), + (162, "RSI_DIVERGENCE", "osc", range(10, 22, 2), (5.0, 10.0)), + (163, "MACD_SLOPE", "osc", range(20, 30, 2), (0.0,)), + (164, "MACD_DIVERGENCE", "osc", range(20, 30, 2), (0.0,)), + (165, "TIME_SINCE_OB", "osc", range(8, 22, 2), (0.0,)), + (166, "TIME_SINCE_OS", "osc", range(8, 22, 2), (0.0,)), + (167, "EXHAUSTION", "osc", range(10, 22, 2), (0.0,)), + (168, "LHLL_SCORE", "trend", range(5, 21, 3), (0.0,)), + ) + ) + return tuple( + IndicatorVariant(i, p, q, r) for i, _, r, ps, qs in specs for p, q in product(ps, qs) + ) + + +HISTORICAL_VARIANTS = _variants() +assert len(HISTORICAL_VARIANTS) == 1107 + +_names = {i: n for i, n, *_ in _SPECS} +_names.update({i: n for i, n, *_ in _COMPACT_SPECS}) +_names.update( + { + variant.indicator_id: _names.get(variant.indicator_id, f"ID_{variant.indicator_id}") + for variant in HISTORICAL_VARIANTS + } +) +HISTORICAL_DEFINITIONS = tuple( + IndicatorDefinition( + i, + _names.get(i, f"RESERVED_{i}"), + next((v.role for v in HISTORICAL_VARIANTS if v.indicator_id == i), None), + ) + for i in sorted({v.indicator_id for v in HISTORICAL_VARIANTS}) +) diff --git a/control_plane/trading_studio/indicators/engine.py b/control_plane/trading_studio/indicators/engine.py new file mode 100644 index 0000000..2cf88aa --- /dev/null +++ b/control_plane/trading_studio/indicators/engine.py @@ -0,0 +1,131 @@ +"""Formula-free execution boundary. It refuses rather than silently falling back.""" + +from __future__ import annotations + +from dataclasses import dataclass +from enum import StrEnum +from typing import Any + +import numpy as np + +from .definitions import IndicatorVariant +from .feature_catalog import FeatureUnavailableError, require_validated_features +from .registry import HISTORICAL_REGISTRY, HS22_REQUIRED_V1, IndicatorRegistry +from .schema import HS22State, parse_hs22 + + +class RefusalCode(StrEnum): + FORMULA_UNAVAILABLE = "formula_unavailable" + UNKNOWN_INDICATOR = "unknown_indicator" + UNSUPPORTED_VARIANT = "unsupported_variant" + UNREGISTERED = "unregistered" + + +@dataclass(frozen=True, slots=True) +class RefusalState: + code: RefusalCode + message: str + all_nan_behavior: bool = False + + +class IndicatorEngine: + def __init__(self, registry: IndicatorRegistry = HISTORICAL_REGISTRY) -> None: + self.registry = registry + + def resolve(self, variant: IndicatorVariant) -> RefusalState: + definition = self.registry.definition(variant.indicator_id) + if definition is None: + return RefusalState( + RefusalCode.UNKNOWN_INDICATOR, "unknown ID returns all-NaN; no fallback", True + ) + if definition.status.value == "unregistered": + return RefusalState( + RefusalCode.UNREGISTERED, "indicator is not registered for execution", True + ) + if self.registry.variant(variant.indicator_id, variant.period, variant.p1) is None: + return RefusalState( + RefusalCode.UNSUPPORTED_VARIANT, "variant is outside the registry", False + ) + return RefusalState( + RefusalCode.FORMULA_UNAVAILABLE, "indicator formulas are not implemented", False + ) + + def compute(self, variant: IndicatorVariant, length: int) -> RefusalState: + # This API intentionally does not emit a numeric fallback array. + if length < 0: + raise ValueError("length must be non-negative") + return self.resolve(variant) + + +def _arrays(close: Any, high: Any, low: Any, volume: Any) -> tuple[np.ndarray, ...]: + arrays = tuple(np.asarray(item, dtype=np.float64) for item in (close, high, low, volume)) + if not arrays[0].ndim == 1 or any(item.shape != arrays[0].shape for item in arrays[1:]): + raise ValueError("HS22 OHLCV inputs must be equally sized one-dimensional arrays") + return arrays + + +def evaluate_indicator( + variant: IndicatorVariant, close: Any, high: Any, low: Any, volume: Any +) -> np.ndarray: + """Evaluate exactly one frozen Cohort001 role triple; all others fail closed.""" + try: + require_validated_features([variant]) + except FeatureUnavailableError as error: + raise ValueError(str(error)) from error + from .historical_formulae import compute_indicator + + close, high, low, volume = _arrays(close, high, low, volume) + return compute_indicator( + variant.indicator_id, close, high, low, volume, variant.period, variant.p1 + ) + + +def signal_color(values: Any) -> np.ndarray: + values = np.asarray(values, dtype=np.float64) + colors = np.zeros(len(values), dtype=np.int8) + previous = 0 + for index in range(1, len(values)): + if np.isnan(values[index]) or np.isnan(values[index - 1]): + previous = 0 + elif values[index] > values[index - 1]: + previous = 1 + elif values[index] < values[index - 1]: + previous = -1 + colors[index] = previous + return colors + + +def compute_hs22_state( + state: HS22State | object, close: Any, high: Any, low: Any, volume: Any +) -> dict[str, np.ndarray]: + """Port of historical ``paper_replay.compute_combo_state`` without a reference import.""" + if not isinstance(state, HS22State): + state = parse_hs22(state, HS22_REQUIRED_V1) + close, high, low, volume = _arrays(close, high, low, volume) + trend = evaluate_indicator(state.trend, close, high, low, volume) + signal = evaluate_indicator(state.signal, close, high, low, volume) + trigger = evaluate_indicator(state.trigger, close, high, low, volume) + confirm = evaluate_indicator(state.confirm, close, high, low, volume) + vol = evaluate_indicator(state.volatility, close, high, low, volume) + return {"trend": trend, "signal": signal, "trigger": trigger, "confirm": confirm, "vol": vol, + "trend_color": signal_color(trend), "signal_color": signal_color(signal)} + + +def analyze_corpus_coverage( + path: str, registry: IndicatorRegistry = HISTORICAL_REGISTRY +) -> dict[str, object]: + """Inspect a parquet corpus when an optional parquet reader is installed.""" + try: + import pyarrow.parquet as parquet # type: ignore[import-not-found] + except ImportError: + return {"available": False, "reason": "pyarrow is not installed"} + table = parquet.read_table(path) + fields = set(table.column_names) + required = {"open", "high", "low", "close", "volume"} + return { + "available": True, + "rows": table.num_rows, + "fields": sorted(fields), + "required_fields_present": required <= fields, + "registered_variants": len(registry.variants), + } diff --git a/control_plane/trading_studio/indicators/feature_catalog.py b/control_plane/trading_studio/indicators/feature_catalog.py new file mode 100644 index 0000000..732e03c --- /dev/null +++ b/control_plane/trading_studio/indicators/feature_catalog.py @@ -0,0 +1,184 @@ +"""Source-only FEATURE_CATALOG_V1 and safety audit for historical features.""" + +from __future__ import annotations + +import hashlib +import json +from dataclasses import asdict, dataclass +from enum import StrEnum +from pathlib import Path + +from .definitions import IndicatorVariant +from .registry import HISTORICAL_REGISTRY, HISTORICAL_VARIANTS, HS22_REQUIRED_V1 + +FEATURE_CATALOG_V1_PATH = Path(__file__).with_name("feature_catalog_v1.json") +FEATURE_SAFETY_AUDIT_V1_PATH = Path(__file__).with_name("feature_safety_audit_v1.json") + + +class FeatureSupportState(StrEnum): + VALIDATED = "validated" + SOURCE_IMPLEMENTED_UNVALIDATED = "source_implemented_unvalidated" + ALIAS_REFUSED = "alias_refused" + UNREGISTERED = "unregistered" + + +class CausalClassification(StrEnum): + TRAILING_WINDOW_CAUSAL = "trailing_window_causal" + INDEX_POSITION_CAUSAL = "index_position_causal" + NOT_EXECUTABLE = "not_executable" + + +class FeatureUnavailableError(ValueError): + """Raised when a requested historical feature lacks validated coverage.""" + + +@dataclass(frozen=True, slots=True) +class FeatureResearchDefinition: + indicator_id: int + name: str + period: int + p1: float + role: str + support_state: FeatureSupportState + causal_classification: CausalClassification + source_semantics: str + + @property + def key(self) -> tuple[int, int, float]: + return self.indicator_id, self.period, self.p1 + + def artifact(self) -> dict[str, object]: + return asdict(self) + + +# These are the 80 distinct formula inputs covered by the frozen Cohort001 +# qualification corpus. A triple may appear in more than one role slot. +VALIDATED_FEATURE_KEYS = frozenset( + (item.indicator_id, item.period, item.p1) for item in HS22_REQUIRED_V1.variants +) +assert len(VALIDATED_FEATURE_KEYS) == 80 + +_INDEX_POSITION_IDS = frozenset({117, 118}) + + +def _source_semantics(variant: IndicatorVariant) -> tuple[CausalClassification, str]: + if variant.indicator_id in _INDEX_POSITION_IDS: + return ( + CausalClassification.INDEX_POSITION_CAUSAL, + "source derives a deterministic cycle from the row index; it does not read future rows", + ) + return ( + CausalClassification.TRAILING_WINDOW_CAUSAL, + "source reads the current row and preceding rows only; " + "completed-bar availability remains required", + ) + + +def feature_definition(variant: IndicatorVariant) -> FeatureResearchDefinition: + definition = HISTORICAL_REGISTRY.definition(variant.indicator_id) + if definition is None: + return FeatureResearchDefinition( + variant.indicator_id, "UNKNOWN", variant.period, variant.p1, variant.role.value, + FeatureSupportState.UNREGISTERED, CausalClassification.NOT_EXECUTABLE, + "not present in the Artifex historical registry", + ) + if definition.status.value == "alias": + return FeatureResearchDefinition( + variant.indicator_id, definition.name, variant.period, variant.p1, variant.role.value, + FeatureSupportState.ALIAS_REFUSED, CausalClassification.NOT_EXECUTABLE, + "historical alias semantics are intentionally not executable", + ) + causal, semantics = _source_semantics(variant) + state = ( + FeatureSupportState.VALIDATED + if (variant.indicator_id, variant.period, variant.p1) in VALIDATED_FEATURE_KEYS + else FeatureSupportState.SOURCE_IMPLEMENTED_UNVALIDATED + ) + return FeatureResearchDefinition( + variant.indicator_id, definition.name, variant.period, variant.p1, variant.role.value, + state, causal, semantics, + ) + + +FEATURE_CATALOG_V1 = tuple(feature_definition(variant) for variant in HISTORICAL_VARIANTS) +assert len(FEATURE_CATALOG_V1) == 1107 + + +def require_validated_features( + variants: tuple[IndicatorVariant, ...] | list[IndicatorVariant], +) -> None: + """Reject the complete request if any member is outside validated coverage.""" + unavailable = [] + for variant in variants: + feature = feature_definition(variant) + if feature.support_state != FeatureSupportState.VALIDATED: + unavailable.append(feature) + if unavailable: + requested = ", ".join( + f"{item.indicator_id}:{item.period}:{item.p1}:{item.role}" for item in unavailable + ) + raise FeatureUnavailableError( + "FEATURE_CATALOG_V1 fails closed: unvalidated or non-executable features requested: " + + requested + ) + + +def feature_catalog_artifact() -> dict[str, object]: + return { + "schema_version": 1, + "catalog": "FEATURE_CATALOG_V1", + "source": "Artifex historical registry; source-semantics audit only", + "evaluation": "not evaluated via reference runtime; no strategy search", + "implementation_coverage": { + "validated_distinct_formula_variants": len(VALIDATED_FEATURE_KEYS), + "historical_registered_variants": len(HISTORICAL_VARIANTS), + "coverage": "80 of 1107", + }, + "features": [item.artifact() for item in FEATURE_CATALOG_V1], + } + + +def feature_safety_audit_artifact() -> dict[str, object]: + catalog = feature_catalog_artifact() + return { + "schema_version": 1, + "audit": "FEATURE_SAFETY_AUDIT_V1", + "source": catalog["source"], + "evaluation": catalog["evaluation"], + "implementation_coverage": catalog["implementation_coverage"], + "support_states": [state.value for state in FeatureSupportState], + "causal_classifications": [classification.value for classification in CausalClassification], + "fail_closed_policy": ( + "Any requested non-validated historical variant rejects the full request; " + "no fallback or baseline expansion." + ), + "findings": [item.artifact() for item in FEATURE_CATALOG_V1], + } + + +def _artifact_bytes(payload: dict[str, object]) -> bytes: + return json.dumps(payload, sort_keys=True, separators=(",", ":"), allow_nan=False).encode() + + +def feature_catalog_artifact_bytes() -> bytes: + return _artifact_bytes(feature_catalog_artifact()) + + +def feature_safety_audit_artifact_bytes() -> bytes: + return _artifact_bytes(feature_safety_audit_artifact()) + + +def feature_catalog_digest() -> str: + return hashlib.sha256(feature_catalog_artifact_bytes()).hexdigest() + + +def feature_safety_audit_digest() -> str: + return hashlib.sha256(feature_safety_audit_artifact_bytes()).hexdigest() + + +def write_feature_artifacts( + catalog_path: Path = FEATURE_CATALOG_V1_PATH, + audit_path: Path = FEATURE_SAFETY_AUDIT_V1_PATH, +) -> None: + catalog_path.write_bytes(feature_catalog_artifact_bytes() + b"\n") + audit_path.write_bytes(feature_safety_audit_artifact_bytes() + b"\n") diff --git a/control_plane/trading_studio/indicators/feature_catalog_v1.json b/control_plane/trading_studio/indicators/feature_catalog_v1.json new file mode 100644 index 0000000..d8beab4 --- /dev/null +++ b/control_plane/trading_studio/indicators/feature_catalog_v1.json @@ -0,0 +1 @@ +{"catalog":"FEATURE_CATALOG_V1","evaluation":"not evaluated via reference runtime; no strategy search","features":[{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":5,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":41,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":44,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":47,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":50,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":5,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":41,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":44,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":47,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":50,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":5,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":41,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":44,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":47,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":50,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":6,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":28,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":34,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":36,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":40,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":42,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":44,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":46,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":48,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":50,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":5,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":5,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":6,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":28,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":-50.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":50.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":100.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":-50.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":0.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":50.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":100.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":-50.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":0.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":50.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":100.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":-50.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":50.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":100.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":-50.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":0.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":50.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":100.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":-50.0,"period":28,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":0.0,"period":28,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":50.0,"period":28,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":100.0,"period":28,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":-50.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":50.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":100.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.6,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.7,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.8,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.9,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.6,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.7,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.8,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.9,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.6,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.7,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.8,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.9,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.6,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.7,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.8,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.9,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.6,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.7,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.8,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.9,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.6,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.7,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.8,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.9,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.6,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.7,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.8,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.9,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.6,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.7,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.8,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.9,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":4.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":6.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":8.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":4.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":6.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":8.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":4.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":6.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":8.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":4.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":6.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":8.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":4.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":6.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":8.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":4.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":6.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":8.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":4.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":6.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":8.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":4.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":6.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":8.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":5,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":13,"name":"VIDYA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":13,"name":"VIDYA","p1":0.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":13,"name":"VIDYA","p1":0.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":13,"name":"VIDYA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":13,"name":"VIDYA","p1":0.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":13,"name":"VIDYA","p1":0.0,"period":28,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":13,"name":"VIDYA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":14,"name":"FRAMA","p1":0.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":14,"name":"FRAMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":14,"name":"FRAMA","p1":0.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":14,"name":"FRAMA","p1":0.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":14,"name":"FRAMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":14,"name":"FRAMA","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":14,"name":"FRAMA","p1":0.0,"period":34,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":14,"name":"FRAMA","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":5,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":1.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":1.5,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.5,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":1.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":1.5,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.5,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":1.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":1.5,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.5,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":1.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":1.5,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.5,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":1.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":1.5,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.5,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":1.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":1.5,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.5,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":2.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":3.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":4.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":2.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":3.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":4.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":2.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":3.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":4.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":2.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":3.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":4.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":20,"name":"DONCHIAN_UPPER","p1":0.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":20,"name":"DONCHIAN_UPPER","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":20,"name":"DONCHIAN_UPPER","p1":0.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":20,"name":"DONCHIAN_UPPER","p1":0.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":20,"name":"DONCHIAN_UPPER","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":21,"name":"DONCHIAN_LOWER","p1":0.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":21,"name":"DONCHIAN_LOWER","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":21,"name":"DONCHIAN_LOWER","p1":0.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":21,"name":"DONCHIAN_LOWER","p1":0.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":21,"name":"DONCHIAN_LOWER","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":22,"name":"DONCHIAN_MID","p1":0.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":22,"name":"DONCHIAN_MID","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":22,"name":"DONCHIAN_MID","p1":0.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":22,"name":"DONCHIAN_MID","p1":0.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":22,"name":"DONCHIAN_MID","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":2.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.5,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":2.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":2.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.5,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":2.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":2.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.5,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":2.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":2.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.5,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":2.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":2.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.5,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":2.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":2.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.5,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":2.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"not_executable","indicator_id":25,"name":"KELTNER_MID","p1":0.0,"period":14,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":25,"name":"KELTNER_MID","p1":0.0,"period":16,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":25,"name":"KELTNER_MID","p1":0.0,"period":18,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":25,"name":"KELTNER_MID","p1":0.0,"period":20,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":25,"name":"KELTNER_MID","p1":0.0,"period":22,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":25,"name":"KELTNER_MID","p1":0.0,"period":24,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":26,"name":"ICHIMOKU_TENKAN","p1":0.0,"period":7,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":26,"name":"ICHIMOKU_TENKAN","p1":0.0,"period":9,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":26,"name":"ICHIMOKU_TENKAN","p1":0.0,"period":11,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":27,"name":"ICHIMOKU_KIJUN","p1":0.0,"period":20,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":27,"name":"ICHIMOKU_KIJUN","p1":0.0,"period":22,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":27,"name":"ICHIMOKU_KIJUN","p1":0.0,"period":24,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":27,"name":"ICHIMOKU_KIJUN","p1":0.0,"period":26,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":27,"name":"ICHIMOKU_KIJUN","p1":0.0,"period":28,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"trailing_window_causal","indicator_id":28,"name":"PSAR","p1":0.01,"period":1,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":28,"name":"PSAR","p1":0.02,"period":1,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":28,"name":"PSAR","p1":0.03,"period":1,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":6,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":24,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":7,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":9,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":13,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":19,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":21,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":7,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":9,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":13,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":19,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":21,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":24,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":28,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":7,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":9,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":13,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":19,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":21,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":35,"name":"ROC","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":35,"name":"ROC","p1":0.0,"period":7,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":35,"name":"ROC","p1":0.0,"period":9,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":35,"name":"ROC","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":35,"name":"ROC","p1":0.0,"period":13,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":35,"name":"ROC","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":35,"name":"ROC","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":35,"name":"ROC","p1":0.0,"period":19,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":36,"name":"CMO","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":36,"name":"CMO","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":36,"name":"CMO","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":36,"name":"CMO","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":36,"name":"CMO","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":36,"name":"CMO","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":36,"name":"CMO","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":37,"name":"TRIX","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":37,"name":"TRIX","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":37,"name":"TRIX","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":37,"name":"TRIX","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":37,"name":"TRIX","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":37,"name":"TRIX","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":37,"name":"TRIX","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":38,"name":"PPO","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":38,"name":"PPO","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":38,"name":"PPO","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":38,"name":"PPO","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":38,"name":"PPO","p1":0.0,"period":24,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":38,"name":"PPO","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":38,"name":"PPO","p1":0.0,"period":28,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":39,"name":"MACD_HIST","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":39,"name":"MACD_HIST","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":39,"name":"MACD_HIST","p1":0.0,"period":24,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":39,"name":"MACD_HIST","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":39,"name":"MACD_HIST","p1":0.0,"period":28,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":39,"name":"MACD_HIST","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":40,"name":"MFI","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":40,"name":"MFI","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":40,"name":"MFI","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":40,"name":"MFI","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":40,"name":"MFI","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":40,"name":"MFI","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":41,"name":"DPO","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":41,"name":"DPO","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":41,"name":"DPO","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":41,"name":"DPO","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":41,"name":"DPO","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":41,"name":"DPO","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":41,"name":"DPO","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":41,"name":"DPO","p1":0.0,"period":24,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":42,"name":"PCTILE_RANK","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":42,"name":"PCTILE_RANK","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":42,"name":"PCTILE_RANK","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":42,"name":"PCTILE_RANK","p1":0.0,"period":32,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":42,"name":"PCTILE_RANK","p1":0.0,"period":38,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":42,"name":"PCTILE_RANK","p1":0.0,"period":44,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":42,"name":"PCTILE_RANK","p1":0.0,"period":50,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":43,"name":"ZSCORE","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":43,"name":"ZSCORE","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":43,"name":"ZSCORE","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":43,"name":"ZSCORE","p1":0.0,"period":32,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":43,"name":"ZSCORE","p1":0.0,"period":38,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":43,"name":"ZSCORE","p1":0.0,"period":44,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":43,"name":"ZSCORE","p1":0.0,"period":50,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":44,"name":"MINMAX","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":44,"name":"MINMAX","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":44,"name":"MINMAX","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":44,"name":"MINMAX","p1":0.0,"period":32,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":44,"name":"MINMAX","p1":0.0,"period":38,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":44,"name":"MINMAX","p1":0.0,"period":44,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":44,"name":"MINMAX","p1":0.0,"period":50,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":90,"name":"MICRO_BODY_RATIO","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":90,"name":"MICRO_BODY_RATIO","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":90,"name":"MICRO_BODY_RATIO","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":90,"name":"MICRO_BODY_RATIO","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":90,"name":"MICRO_BODY_RATIO","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":90,"name":"MICRO_BODY_RATIO","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":91,"name":"MICRO_UPPER_WICK","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":91,"name":"MICRO_UPPER_WICK","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":91,"name":"MICRO_UPPER_WICK","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":91,"name":"MICRO_UPPER_WICK","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":91,"name":"MICRO_UPPER_WICK","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":91,"name":"MICRO_UPPER_WICK","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":92,"name":"MICRO_LOWER_WICK","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":92,"name":"MICRO_LOWER_WICK","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":92,"name":"MICRO_LOWER_WICK","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":92,"name":"MICRO_LOWER_WICK","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":92,"name":"MICRO_LOWER_WICK","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":92,"name":"MICRO_LOWER_WICK","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":93,"name":"MICRO_BUY_PRESSURE","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":93,"name":"MICRO_BUY_PRESSURE","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":93,"name":"MICRO_BUY_PRESSURE","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":93,"name":"MICRO_BUY_PRESSURE","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":93,"name":"MICRO_BUY_PRESSURE","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":93,"name":"MICRO_BUY_PRESSURE","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":94,"name":"MICRO_SELL_PRESSURE","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":94,"name":"MICRO_SELL_PRESSURE","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":94,"name":"MICRO_SELL_PRESSURE","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":94,"name":"MICRO_SELL_PRESSURE","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":94,"name":"MICRO_SELL_PRESSURE","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":94,"name":"MICRO_SELL_PRESSURE","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":95,"name":"MICRO_STOP_HUNT","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":95,"name":"MICRO_STOP_HUNT","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":95,"name":"MICRO_STOP_HUNT","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":96,"name":"MICRO_FVG","p1":0.0,"period":1,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":97,"name":"MICRO_LIQ_SWEEP","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":97,"name":"MICRO_LIQ_SWEEP","p1":0.0,"period":9,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":97,"name":"MICRO_LIQ_SWEEP","p1":0.0,"period":13,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":97,"name":"MICRO_LIQ_SWEEP","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":98,"name":"TREND_BREAKOUT","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":98,"name":"TREND_BREAKOUT","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":98,"name":"TREND_BREAKOUT","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":98,"name":"TREND_BREAKOUT","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":98,"name":"TREND_BREAKOUT","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":99,"name":"TREND_PULLBACK","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":99,"name":"TREND_PULLBACK","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":99,"name":"TREND_PULLBACK","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":99,"name":"TREND_PULLBACK","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":99,"name":"TREND_PULLBACK","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":100,"name":"MOM_VELOCITY","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":100,"name":"MOM_VELOCITY","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":100,"name":"MOM_VELOCITY","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":100,"name":"MOM_VELOCITY","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":100,"name":"MOM_VELOCITY","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":100,"name":"MOM_VELOCITY","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":101,"name":"MOM_ACCELERATION","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":101,"name":"MOM_ACCELERATION","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":101,"name":"MOM_ACCELERATION","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":101,"name":"MOM_ACCELERATION","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":101,"name":"MOM_ACCELERATION","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":101,"name":"MOM_ACCELERATION","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":102,"name":"MOM_COMPOSITE","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":102,"name":"MOM_COMPOSITE","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":102,"name":"MOM_COMPOSITE","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":102,"name":"MOM_COMPOSITE","p1":0.0,"period":24,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":102,"name":"MOM_COMPOSITE","p1":0.0,"period":28,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":103,"name":"MOM_NORMALIZED_ROC","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":103,"name":"MOM_NORMALIZED_ROC","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":103,"name":"MOM_NORMALIZED_ROC","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":103,"name":"MOM_NORMALIZED_ROC","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":103,"name":"MOM_NORMALIZED_ROC","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":103,"name":"MOM_NORMALIZED_ROC","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","p1":0.0,"period":23,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","p1":0.0,"period":29,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":105,"name":"CROSS_EMA_SPREAD","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":105,"name":"CROSS_EMA_SPREAD","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":105,"name":"CROSS_EMA_SPREAD","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":105,"name":"CROSS_EMA_SPREAD","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":105,"name":"CROSS_EMA_SPREAD","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":105,"name":"CROSS_EMA_SPREAD","p1":0.0,"period":34,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":105,"name":"CROSS_EMA_SPREAD","p1":0.0,"period":38,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":106,"name":"CROSS_MOM_X_VOL","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":106,"name":"CROSS_MOM_X_VOL","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":106,"name":"CROSS_MOM_X_VOL","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":106,"name":"CROSS_MOM_X_VOL","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":106,"name":"CROSS_MOM_X_VOL","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":107,"name":"CROSS_VOL_ADJ_MOM","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":107,"name":"CROSS_VOL_ADJ_MOM","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":107,"name":"CROSS_VOL_ADJ_MOM","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":107,"name":"CROSS_VOL_ADJ_MOM","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":107,"name":"CROSS_VOL_ADJ_MOM","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":108,"name":"NORM_RETURN_ZSCORE","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":108,"name":"NORM_RETURN_ZSCORE","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":108,"name":"NORM_RETURN_ZSCORE","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":108,"name":"NORM_RETURN_ZSCORE","p1":0.0,"period":32,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":108,"name":"NORM_RETURN_ZSCORE","p1":0.0,"period":38,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":108,"name":"NORM_RETURN_ZSCORE","p1":0.0,"period":44,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":108,"name":"NORM_RETURN_ZSCORE","p1":0.0,"period":50,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":109,"name":"TIME_BARS_SINCE_HIGH","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":109,"name":"TIME_BARS_SINCE_HIGH","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":109,"name":"TIME_BARS_SINCE_HIGH","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":109,"name":"TIME_BARS_SINCE_HIGH","p1":0.0,"period":40,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":109,"name":"TIME_BARS_SINCE_HIGH","p1":0.0,"period":50,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":110,"name":"TIME_BARS_SINCE_LOW","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":110,"name":"TIME_BARS_SINCE_LOW","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":110,"name":"TIME_BARS_SINCE_LOW","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":110,"name":"TIME_BARS_SINCE_LOW","p1":0.0,"period":40,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":110,"name":"TIME_BARS_SINCE_LOW","p1":0.0,"period":50,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":116,"name":"REGIME_SKEWNESS","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":116,"name":"REGIME_SKEWNESS","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":116,"name":"REGIME_SKEWNESS","p1":0.0,"period":40,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":116,"name":"REGIME_SKEWNESS","p1":0.0,"period":50,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":116,"name":"REGIME_SKEWNESS","p1":0.0,"period":60,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":52,"name":"VOL_ATR_ZSCORE","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":52,"name":"VOL_ATR_ZSCORE","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":52,"name":"VOL_ATR_ZSCORE","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":52,"name":"VOL_ATR_ZSCORE","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":52,"name":"VOL_ATR_ZSCORE","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":59,"name":"VOL_RANGE_PCTILE","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":59,"name":"VOL_RANGE_PCTILE","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":59,"name":"VOL_RANGE_PCTILE","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":59,"name":"VOL_RANGE_PCTILE","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":59,"name":"VOL_RANGE_PCTILE","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":60,"name":"VOL_TR_MOMENTUM","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":60,"name":"VOL_TR_MOMENTUM","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":60,"name":"VOL_TR_MOMENTUM","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":60,"name":"VOL_TR_MOMENTUM","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":60,"name":"VOL_TR_MOMENTUM","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":70,"name":"ADX","p1":0.0,"period":10,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":70,"name":"ADX","p1":0.0,"period":12,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":70,"name":"ADX","p1":0.0,"period":14,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":70,"name":"ADX","p1":0.0,"period":16,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":70,"name":"ADX","p1":0.0,"period":18,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":70,"name":"ADX","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":71,"name":"AROON_UP","p1":0.0,"period":10,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":71,"name":"AROON_UP","p1":0.0,"period":14,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":71,"name":"AROON_UP","p1":0.0,"period":18,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":71,"name":"AROON_UP","p1":0.0,"period":22,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":71,"name":"AROON_UP","p1":0.0,"period":26,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":72,"name":"AROON_DOWN","p1":0.0,"period":10,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":72,"name":"AROON_DOWN","p1":0.0,"period":14,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":72,"name":"AROON_DOWN","p1":0.0,"period":18,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":72,"name":"AROON_DOWN","p1":0.0,"period":22,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":72,"name":"AROON_DOWN","p1":0.0,"period":26,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":73,"name":"LINREG_SLOPE","p1":0.0,"period":8,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":73,"name":"LINREG_SLOPE","p1":0.0,"period":11,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":73,"name":"LINREG_SLOPE","p1":0.0,"period":14,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":73,"name":"LINREG_SLOPE","p1":0.0,"period":17,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":73,"name":"LINREG_SLOPE","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":73,"name":"LINREG_SLOPE","p1":0.0,"period":23,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":73,"name":"LINREG_SLOPE","p1":0.0,"period":26,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":73,"name":"LINREG_SLOPE","p1":0.0,"period":29,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":74,"name":"LINREG_R2","p1":0.0,"period":8,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":74,"name":"LINREG_R2","p1":0.0,"period":11,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":74,"name":"LINREG_R2","p1":0.0,"period":14,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":74,"name":"LINREG_R2","p1":0.0,"period":17,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":74,"name":"LINREG_R2","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":74,"name":"LINREG_R2","p1":0.0,"period":23,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":74,"name":"LINREG_R2","p1":0.0,"period":26,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":74,"name":"LINREG_R2","p1":0.0,"period":29,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":75,"name":"EFFICIENCY","p1":0.0,"period":8,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":75,"name":"EFFICIENCY","p1":0.0,"period":11,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":75,"name":"EFFICIENCY","p1":0.0,"period":14,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":75,"name":"EFFICIENCY","p1":0.0,"period":17,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":75,"name":"EFFICIENCY","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":75,"name":"EFFICIENCY","p1":0.0,"period":23,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":75,"name":"EFFICIENCY","p1":0.0,"period":26,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":75,"name":"EFFICIENCY","p1":0.0,"period":29,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":76,"name":"ANGLE","p1":0.0,"period":8,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":76,"name":"ANGLE","p1":0.0,"period":11,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":76,"name":"ANGLE","p1":0.0,"period":14,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":76,"name":"ANGLE","p1":0.0,"period":17,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":76,"name":"ANGLE","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":76,"name":"ANGLE","p1":0.0,"period":23,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":76,"name":"ANGLE","p1":0.0,"period":26,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":76,"name":"ANGLE","p1":0.0,"period":29,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":77,"name":"DURATION","p1":0.0,"period":1,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":78,"name":"HURST","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":78,"name":"HURST","p1":0.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":78,"name":"HURST","p1":0.0,"period":40,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":78,"name":"HURST","p1":0.0,"period":50,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":78,"name":"HURST","p1":0.0,"period":60,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":80,"name":"FRACTAL_DIM","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":80,"name":"FRACTAL_DIM","p1":0.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":80,"name":"FRACTAL_DIM","p1":0.0,"period":40,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":80,"name":"FRACTAL_DIM","p1":0.0,"period":50,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":80,"name":"FRACTAL_DIM","p1":0.0,"period":60,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":81,"name":"TREND_PERSIST","p1":0.0,"period":10,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":81,"name":"TREND_PERSIST","p1":0.0,"period":15,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":81,"name":"TREND_PERSIST","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":81,"name":"TREND_PERSIST","p1":0.0,"period":25,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":81,"name":"TREND_PERSIST","p1":0.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":83,"name":"MICRO_TREND_STRUCT","p1":0.0,"period":5,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":83,"name":"MICRO_TREND_STRUCT","p1":0.0,"period":8,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":83,"name":"MICRO_TREND_STRUCT","p1":0.0,"period":11,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":83,"name":"MICRO_TREND_STRUCT","p1":0.0,"period":14,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":83,"name":"MICRO_TREND_STRUCT","p1":0.0,"period":17,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":83,"name":"MICRO_TREND_STRUCT","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":2.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":4.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":8.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":2.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":4.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":8.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":2.0,"period":40,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":4.0,"period":40,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":8.0,"period":40,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":2.0,"period":50,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":4.0,"period":50,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":8.0,"period":50,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":2.0,"period":60,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":4.0,"period":60,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":8.0,"period":60,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":1.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":3.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":5.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":1.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":3.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":5.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":1.0,"period":40,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":3.0,"period":40,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":5.0,"period":40,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":1.0,"period":50,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":3.0,"period":50,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":5.0,"period":50,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":50,"name":"ID_50","p1":0.0,"period":8,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":50,"name":"ID_50","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":50,"name":"ID_50","p1":0.0,"period":12,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":50,"name":"ID_50","p1":0.0,"period":14,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":50,"name":"ID_50","p1":0.0,"period":16,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":50,"name":"ID_50","p1":0.0,"period":18,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":50,"name":"ID_50","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":51,"name":"ID_51","p1":0.0,"period":8,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":51,"name":"ID_51","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":51,"name":"ID_51","p1":0.0,"period":12,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":51,"name":"ID_51","p1":0.0,"period":14,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":51,"name":"ID_51","p1":0.0,"period":16,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":51,"name":"ID_51","p1":0.0,"period":18,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":51,"name":"ID_51","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":53,"name":"ID_53","p1":0.0,"period":14,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":53,"name":"ID_53","p1":0.0,"period":18,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":53,"name":"ID_53","p1":0.0,"period":22,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":53,"name":"ID_53","p1":0.0,"period":26,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":53,"name":"ID_53","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":54,"name":"ID_54","p1":0.0,"period":14,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":54,"name":"ID_54","p1":0.0,"period":18,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":54,"name":"ID_54","p1":0.0,"period":22,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":54,"name":"ID_54","p1":0.0,"period":26,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":54,"name":"ID_54","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":55,"name":"ID_55","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":55,"name":"ID_55","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":55,"name":"ID_55","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":55,"name":"ID_55","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":55,"name":"ID_55","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":56,"name":"ID_56","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":56,"name":"ID_56","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":56,"name":"ID_56","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":56,"name":"ID_56","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":56,"name":"ID_56","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":57,"name":"ID_57","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":57,"name":"ID_57","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":57,"name":"ID_57","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":57,"name":"ID_57","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":57,"name":"ID_57","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":58,"name":"ID_58","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":58,"name":"ID_58","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":58,"name":"ID_58","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":58,"name":"ID_58","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":58,"name":"ID_58","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":61,"name":"ID_61","p1":0.0,"period":14,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":61,"name":"ID_61","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":61,"name":"ID_61","p1":0.0,"period":26,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":61,"name":"ID_61","p1":0.0,"period":32,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":61,"name":"ID_61","p1":0.0,"period":38,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":61,"name":"ID_61","p1":0.0,"period":44,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":61,"name":"ID_61","p1":0.0,"period":50,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":63,"name":"ID_63","p1":0.0,"period":5,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":63,"name":"ID_63","p1":0.0,"period":8,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":63,"name":"ID_63","p1":0.0,"period":11,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":63,"name":"ID_63","p1":0.0,"period":14,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":63,"name":"ID_63","p1":0.0,"period":17,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":63,"name":"ID_63","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":111,"name":"ID_111","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":111,"name":"ID_111","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":111,"name":"ID_111","p1":0.0,"period":40,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":111,"name":"ID_111","p1":0.0,"period":50,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":111,"name":"ID_111","p1":0.0,"period":60,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":112,"name":"ID_112","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":112,"name":"ID_112","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":112,"name":"ID_112","p1":0.0,"period":40,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":112,"name":"ID_112","p1":0.0,"period":50,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":112,"name":"ID_112","p1":0.0,"period":60,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":113,"name":"ID_113","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":113,"name":"ID_113","p1":0.0,"period":40,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":113,"name":"ID_113","p1":0.0,"period":50,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":113,"name":"ID_113","p1":0.0,"period":60,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":115,"name":"ID_115","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":115,"name":"ID_115","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":115,"name":"ID_115","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":115,"name":"ID_115","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":115,"name":"ID_115","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"index_position_causal","indicator_id":118,"name":"ID_118","p1":0.0,"period":1,"role":"filter","source_semantics":"source derives a deterministic cycle from the row index; it does not read future rows","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":119,"name":"ID_119","p1":0.0,"period":1,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":62,"name":"ID_62","p1":0.0,"period":10,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":62,"name":"ID_62","p1":0.0,"period":15,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":62,"name":"ID_62","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":62,"name":"ID_62","p1":0.0,"period":25,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":62,"name":"ID_62","p1":0.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"index_position_causal","indicator_id":117,"name":"ID_117","p1":0.0,"period":1,"role":"trend","source_semantics":"source derives a deterministic cycle from the row index; it does not read future rows","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":10.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":20.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":50.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":10.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":20.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":50.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":10.0,"period":40,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":20.0,"period":40,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":50.0,"period":40,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":10.0,"period":50,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":20.0,"period":50,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":50.0,"period":50,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":60,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":90,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":120,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":150,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":180,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":210,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":240,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":270,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":300,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":330,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":360,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":60,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":90,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":120,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":150,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":180,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":210,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":240,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":270,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":300,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":330,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":360,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":60,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":90,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":120,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":150,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":180,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":210,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":240,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":270,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":300,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":330,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":360,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":60,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":90,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":120,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":150,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":180,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":210,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":240,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":270,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":300,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":330,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":360,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":60,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":90,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":120,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":150,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":180,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":210,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":240,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":270,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":300,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":330,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":360,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":60,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":90,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":120,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":150,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":180,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":210,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":240,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":270,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":300,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":330,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":360,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":60,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":90,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":120,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":150,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":180,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":210,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":240,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":270,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":300,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":330,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":360,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":127,"name":"ID_127","p1":0.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":127,"name":"ID_127","p1":0.0,"period":15,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":127,"name":"ID_127","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":127,"name":"ID_127","p1":0.0,"period":25,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":127,"name":"ID_127","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":127,"name":"ID_127","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":127,"name":"ID_127","p1":0.0,"period":40,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":1.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":1.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":1.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":1.5,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.5,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":1.5,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.5,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":1.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":1.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":1.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":1.5,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.5,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":1.5,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.5,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":130,"name":"ID_130","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":130,"name":"ID_130","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":130,"name":"ID_130","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":130,"name":"ID_130","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":130,"name":"ID_130","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":131,"name":"ID_131","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":131,"name":"ID_131","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":131,"name":"ID_131","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":131,"name":"ID_131","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":131,"name":"ID_131","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":135,"name":"ID_135","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":135,"name":"ID_135","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":135,"name":"ID_135","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":135,"name":"ID_135","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":135,"name":"ID_135","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":136,"name":"ID_136","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":136,"name":"ID_136","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":136,"name":"ID_136","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":136,"name":"ID_136","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":136,"name":"ID_136","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":137,"name":"ID_137","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":137,"name":"ID_137","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":137,"name":"ID_137","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":137,"name":"ID_137","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":137,"name":"ID_137","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":138,"name":"ID_138","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":138,"name":"ID_138","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":138,"name":"ID_138","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":139,"name":"ID_139","p1":0.0,"period":1,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":140,"name":"ID_140","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":140,"name":"ID_140","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":140,"name":"ID_140","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":141,"name":"ID_141","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":141,"name":"ID_141","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":141,"name":"ID_141","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":141,"name":"ID_141","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":141,"name":"ID_141","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":142,"name":"ID_142","p1":0.0,"period":1,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":143,"name":"ID_143","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":143,"name":"ID_143","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":143,"name":"ID_143","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":143,"name":"ID_143","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":143,"name":"ID_143","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":144,"name":"ID_144","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":144,"name":"ID_144","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":144,"name":"ID_144","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":144,"name":"ID_144","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":144,"name":"ID_144","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":145,"name":"ID_145","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":145,"name":"ID_145","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":145,"name":"ID_145","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":145,"name":"ID_145","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":145,"name":"ID_145","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":146,"name":"ID_146","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":146,"name":"ID_146","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":146,"name":"ID_146","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":146,"name":"ID_146","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":146,"name":"ID_146","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":147,"name":"ID_147","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":147,"name":"ID_147","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":147,"name":"ID_147","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":147,"name":"ID_147","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":147,"name":"ID_147","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":150,"name":"ID_150","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":150,"name":"ID_150","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":150,"name":"ID_150","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":150,"name":"ID_150","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":150,"name":"ID_150","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":151,"name":"ID_151","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":151,"name":"ID_151","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":151,"name":"ID_151","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":151,"name":"ID_151","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":151,"name":"ID_151","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":152,"name":"ID_152","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":152,"name":"ID_152","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":152,"name":"ID_152","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":152,"name":"ID_152","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":152,"name":"ID_152","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":153,"name":"ID_153","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":153,"name":"ID_153","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":153,"name":"ID_153","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":153,"name":"ID_153","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":153,"name":"ID_153","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":154,"name":"ID_154","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":154,"name":"ID_154","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":154,"name":"ID_154","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":155,"name":"ID_155","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":155,"name":"ID_155","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":155,"name":"ID_155","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":155,"name":"ID_155","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":155,"name":"ID_155","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":156,"name":"ID_156","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":156,"name":"ID_156","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":156,"name":"ID_156","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":156,"name":"ID_156","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":156,"name":"ID_156","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":157,"name":"ID_157","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":157,"name":"ID_157","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":157,"name":"ID_157","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":157,"name":"ID_157","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":157,"name":"ID_157","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":158,"name":"ID_158","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":158,"name":"ID_158","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":158,"name":"ID_158","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":158,"name":"ID_158","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":158,"name":"ID_158","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":160,"name":"ID_160","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":160,"name":"ID_160","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":160,"name":"ID_160","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":160,"name":"ID_160","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":160,"name":"ID_160","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":160,"name":"ID_160","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":160,"name":"ID_160","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":161,"name":"ID_161","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":161,"name":"ID_161","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":161,"name":"ID_161","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":161,"name":"ID_161","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":161,"name":"ID_161","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":161,"name":"ID_161","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":161,"name":"ID_161","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":5.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":10.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":5.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":10.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":5.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":10.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":5.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":10.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":5.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":10.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":5.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":10.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":163,"name":"ID_163","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":163,"name":"ID_163","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":163,"name":"ID_163","p1":0.0,"period":24,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":163,"name":"ID_163","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":163,"name":"ID_163","p1":0.0,"period":28,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":164,"name":"ID_164","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":164,"name":"ID_164","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":164,"name":"ID_164","p1":0.0,"period":24,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":164,"name":"ID_164","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":164,"name":"ID_164","p1":0.0,"period":28,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":165,"name":"ID_165","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":165,"name":"ID_165","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":165,"name":"ID_165","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":165,"name":"ID_165","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":165,"name":"ID_165","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":165,"name":"ID_165","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":165,"name":"ID_165","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":166,"name":"ID_166","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":166,"name":"ID_166","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":166,"name":"ID_166","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":166,"name":"ID_166","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":166,"name":"ID_166","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":166,"name":"ID_166","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":166,"name":"ID_166","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":167,"name":"ID_167","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":167,"name":"ID_167","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":167,"name":"ID_167","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":167,"name":"ID_167","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":167,"name":"ID_167","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":167,"name":"ID_167","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":168,"name":"ID_168","p1":0.0,"period":5,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":168,"name":"ID_168","p1":0.0,"period":8,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":168,"name":"ID_168","p1":0.0,"period":11,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":168,"name":"ID_168","p1":0.0,"period":14,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":168,"name":"ID_168","p1":0.0,"period":17,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":168,"name":"ID_168","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"}],"implementation_coverage":{"coverage":"80 of 1107","historical_registered_variants":1107,"validated_distinct_formula_variants":80},"schema_version":1,"source":"Artifex historical registry; source-semantics audit only"} diff --git a/control_plane/trading_studio/indicators/feature_safety_audit_v1.json b/control_plane/trading_studio/indicators/feature_safety_audit_v1.json new file mode 100644 index 0000000..211768b --- /dev/null +++ b/control_plane/trading_studio/indicators/feature_safety_audit_v1.json @@ -0,0 +1 @@ +{"audit":"FEATURE_SAFETY_AUDIT_V1","causal_classifications":["trailing_window_causal","index_position_causal","not_executable"],"evaluation":"not evaluated via reference runtime; no strategy search","fail_closed_policy":"Any requested non-validated historical variant rejects the full request; no fallback or baseline expansion.","findings":[{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":5,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":41,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":44,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":47,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":0,"name":"SMA","p1":0.0,"period":50,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":5,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":41,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":44,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":47,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":1,"name":"EMA","p1":0.0,"period":50,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":5,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":41,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":44,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":47,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":2,"name":"WMA","p1":0.0,"period":50,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":6,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":28,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":34,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":36,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":40,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":42,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":44,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":46,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":48,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":3,"name":"HMA","p1":0.0,"period":50,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":5,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":4,"name":"DEMA","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":5,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":5,"name":"TEMA","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":6,"name":"KAMA","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":6,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":28,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":7,"name":"EHLERS_SS","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":8,"name":"MCGINLEY","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":-50.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":50.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":100.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":-50.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":0.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":50.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":100.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":-50.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":0.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":50.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":100.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":-50.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":50.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":100.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":-50.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":0.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":50.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":100.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":-50.0,"period":28,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":0.0,"period":28,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":50.0,"period":28,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":100.0,"period":28,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":-50.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":50.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":9,"name":"JMA","p1":100.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.6,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.7,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.8,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.9,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.6,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.7,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.8,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.9,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.6,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.7,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.8,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.9,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.6,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.7,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.8,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.9,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.6,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.7,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.8,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.9,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.6,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.7,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.8,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.9,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.6,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.7,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.8,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.9,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.6,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.7,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.8,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":10,"name":"T3","p1":0.9,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":4.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":6.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":8.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":4.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":6.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":8.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":4.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":6.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":8.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":4.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":6.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":8.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":4.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":6.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":8.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":4.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":6.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":8.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":4.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":6.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":8.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":4.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":6.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":11,"name":"ALMA","p1":8.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":5,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":12,"name":"ZLEMA","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":13,"name":"VIDYA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":13,"name":"VIDYA","p1":0.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":13,"name":"VIDYA","p1":0.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":13,"name":"VIDYA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":13,"name":"VIDYA","p1":0.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":13,"name":"VIDYA","p1":0.0,"period":28,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":13,"name":"VIDYA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":14,"name":"FRAMA","p1":0.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":14,"name":"FRAMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":14,"name":"FRAMA","p1":0.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":14,"name":"FRAMA","p1":0.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":14,"name":"FRAMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":14,"name":"FRAMA","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":14,"name":"FRAMA","p1":0.0,"period":34,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":14,"name":"FRAMA","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":15,"name":"LSMA","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":5,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":11,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":17,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":23,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":16,"name":"SWMA","p1":0.0,"period":29,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":1.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":1.5,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.5,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":1.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":1.5,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.5,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":1.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":1.5,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":17,"name":"BB_UPPER","p1":2.5,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":1.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":1.5,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.5,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":1.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":1.5,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.5,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":1.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":1.5,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":18,"name":"BB_LOWER","p1":2.5,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":2.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":3.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":4.0,"period":8,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":2.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":3.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":4.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":2.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":3.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":4.0,"period":12,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":2.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":3.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":19,"name":"SUPERTREND","p1":4.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":20,"name":"DONCHIAN_UPPER","p1":0.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":20,"name":"DONCHIAN_UPPER","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":20,"name":"DONCHIAN_UPPER","p1":0.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":20,"name":"DONCHIAN_UPPER","p1":0.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":20,"name":"DONCHIAN_UPPER","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":21,"name":"DONCHIAN_LOWER","p1":0.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":21,"name":"DONCHIAN_LOWER","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":21,"name":"DONCHIAN_LOWER","p1":0.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":21,"name":"DONCHIAN_LOWER","p1":0.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":21,"name":"DONCHIAN_LOWER","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":22,"name":"DONCHIAN_MID","p1":0.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":22,"name":"DONCHIAN_MID","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":22,"name":"DONCHIAN_MID","p1":0.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":22,"name":"DONCHIAN_MID","p1":0.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":22,"name":"DONCHIAN_MID","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":2.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.5,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":2.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":2.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.5,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":2.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":2.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":1.5,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":23,"name":"KELTNER_UPPER","p1":2.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":2.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.5,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":2.0,"period":16,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":2.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.5,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":2.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":2.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":1.5,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":24,"name":"KELTNER_LOWER","p1":2.0,"period":24,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"not_executable","indicator_id":25,"name":"KELTNER_MID","p1":0.0,"period":14,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":25,"name":"KELTNER_MID","p1":0.0,"period":16,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":25,"name":"KELTNER_MID","p1":0.0,"period":18,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":25,"name":"KELTNER_MID","p1":0.0,"period":20,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":25,"name":"KELTNER_MID","p1":0.0,"period":22,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":25,"name":"KELTNER_MID","p1":0.0,"period":24,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":26,"name":"ICHIMOKU_TENKAN","p1":0.0,"period":7,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":26,"name":"ICHIMOKU_TENKAN","p1":0.0,"period":9,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":26,"name":"ICHIMOKU_TENKAN","p1":0.0,"period":11,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":27,"name":"ICHIMOKU_KIJUN","p1":0.0,"period":20,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":27,"name":"ICHIMOKU_KIJUN","p1":0.0,"period":22,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":27,"name":"ICHIMOKU_KIJUN","p1":0.0,"period":24,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":27,"name":"ICHIMOKU_KIJUN","p1":0.0,"period":26,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"not_executable","indicator_id":27,"name":"ICHIMOKU_KIJUN","p1":0.0,"period":28,"role":"level","source_semantics":"historical alias semantics are intentionally not executable","support_state":"alias_refused"},{"causal_classification":"trailing_window_causal","indicator_id":28,"name":"PSAR","p1":0.01,"period":1,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":28,"name":"PSAR","p1":0.02,"period":1,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":28,"name":"PSAR","p1":0.03,"period":1,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":6,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":24,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":30,"name":"RSI","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":7,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":9,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":13,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":19,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":31,"name":"STOCH_K","p1":0.0,"period":21,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":7,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":9,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":13,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":19,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":32,"name":"STOCH_D","p1":0.0,"period":21,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":24,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":33,"name":"CCI","p1":0.0,"period":28,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":7,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":9,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":13,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":19,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":34,"name":"WILLIAMS_R","p1":0.0,"period":21,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":35,"name":"ROC","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":35,"name":"ROC","p1":0.0,"period":7,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":35,"name":"ROC","p1":0.0,"period":9,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":35,"name":"ROC","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":35,"name":"ROC","p1":0.0,"period":13,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":35,"name":"ROC","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":35,"name":"ROC","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":35,"name":"ROC","p1":0.0,"period":19,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":36,"name":"CMO","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":36,"name":"CMO","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":36,"name":"CMO","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":36,"name":"CMO","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":36,"name":"CMO","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":36,"name":"CMO","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":36,"name":"CMO","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":37,"name":"TRIX","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":37,"name":"TRIX","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":37,"name":"TRIX","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":37,"name":"TRIX","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":37,"name":"TRIX","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":37,"name":"TRIX","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":37,"name":"TRIX","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":38,"name":"PPO","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":38,"name":"PPO","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":38,"name":"PPO","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":38,"name":"PPO","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":38,"name":"PPO","p1":0.0,"period":24,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":38,"name":"PPO","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":38,"name":"PPO","p1":0.0,"period":28,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":39,"name":"MACD_HIST","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":39,"name":"MACD_HIST","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":39,"name":"MACD_HIST","p1":0.0,"period":24,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":39,"name":"MACD_HIST","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":39,"name":"MACD_HIST","p1":0.0,"period":28,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":39,"name":"MACD_HIST","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":40,"name":"MFI","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":40,"name":"MFI","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":40,"name":"MFI","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":40,"name":"MFI","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":40,"name":"MFI","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":40,"name":"MFI","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":41,"name":"DPO","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":41,"name":"DPO","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":41,"name":"DPO","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":41,"name":"DPO","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":41,"name":"DPO","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":41,"name":"DPO","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":41,"name":"DPO","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":41,"name":"DPO","p1":0.0,"period":24,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":42,"name":"PCTILE_RANK","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":42,"name":"PCTILE_RANK","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":42,"name":"PCTILE_RANK","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":42,"name":"PCTILE_RANK","p1":0.0,"period":32,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":42,"name":"PCTILE_RANK","p1":0.0,"period":38,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":42,"name":"PCTILE_RANK","p1":0.0,"period":44,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":42,"name":"PCTILE_RANK","p1":0.0,"period":50,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":43,"name":"ZSCORE","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":43,"name":"ZSCORE","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":43,"name":"ZSCORE","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":43,"name":"ZSCORE","p1":0.0,"period":32,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":43,"name":"ZSCORE","p1":0.0,"period":38,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":43,"name":"ZSCORE","p1":0.0,"period":44,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":43,"name":"ZSCORE","p1":0.0,"period":50,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":44,"name":"MINMAX","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":44,"name":"MINMAX","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":44,"name":"MINMAX","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":44,"name":"MINMAX","p1":0.0,"period":32,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":44,"name":"MINMAX","p1":0.0,"period":38,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":44,"name":"MINMAX","p1":0.0,"period":44,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":44,"name":"MINMAX","p1":0.0,"period":50,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":90,"name":"MICRO_BODY_RATIO","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":90,"name":"MICRO_BODY_RATIO","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":90,"name":"MICRO_BODY_RATIO","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":90,"name":"MICRO_BODY_RATIO","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":90,"name":"MICRO_BODY_RATIO","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":90,"name":"MICRO_BODY_RATIO","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":91,"name":"MICRO_UPPER_WICK","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":91,"name":"MICRO_UPPER_WICK","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":91,"name":"MICRO_UPPER_WICK","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":91,"name":"MICRO_UPPER_WICK","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":91,"name":"MICRO_UPPER_WICK","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":91,"name":"MICRO_UPPER_WICK","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":92,"name":"MICRO_LOWER_WICK","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":92,"name":"MICRO_LOWER_WICK","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":92,"name":"MICRO_LOWER_WICK","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":92,"name":"MICRO_LOWER_WICK","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":92,"name":"MICRO_LOWER_WICK","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":92,"name":"MICRO_LOWER_WICK","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":93,"name":"MICRO_BUY_PRESSURE","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":93,"name":"MICRO_BUY_PRESSURE","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":93,"name":"MICRO_BUY_PRESSURE","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":93,"name":"MICRO_BUY_PRESSURE","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":93,"name":"MICRO_BUY_PRESSURE","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":93,"name":"MICRO_BUY_PRESSURE","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":94,"name":"MICRO_SELL_PRESSURE","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":94,"name":"MICRO_SELL_PRESSURE","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":94,"name":"MICRO_SELL_PRESSURE","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":94,"name":"MICRO_SELL_PRESSURE","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":94,"name":"MICRO_SELL_PRESSURE","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":94,"name":"MICRO_SELL_PRESSURE","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":95,"name":"MICRO_STOP_HUNT","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":95,"name":"MICRO_STOP_HUNT","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":95,"name":"MICRO_STOP_HUNT","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":96,"name":"MICRO_FVG","p1":0.0,"period":1,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":97,"name":"MICRO_LIQ_SWEEP","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":97,"name":"MICRO_LIQ_SWEEP","p1":0.0,"period":9,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":97,"name":"MICRO_LIQ_SWEEP","p1":0.0,"period":13,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":97,"name":"MICRO_LIQ_SWEEP","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":98,"name":"TREND_BREAKOUT","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":98,"name":"TREND_BREAKOUT","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":98,"name":"TREND_BREAKOUT","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":98,"name":"TREND_BREAKOUT","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":98,"name":"TREND_BREAKOUT","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":99,"name":"TREND_PULLBACK","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":99,"name":"TREND_PULLBACK","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":99,"name":"TREND_PULLBACK","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":99,"name":"TREND_PULLBACK","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":99,"name":"TREND_PULLBACK","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":100,"name":"MOM_VELOCITY","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":100,"name":"MOM_VELOCITY","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":100,"name":"MOM_VELOCITY","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":100,"name":"MOM_VELOCITY","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":100,"name":"MOM_VELOCITY","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":100,"name":"MOM_VELOCITY","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":101,"name":"MOM_ACCELERATION","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":101,"name":"MOM_ACCELERATION","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":101,"name":"MOM_ACCELERATION","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":101,"name":"MOM_ACCELERATION","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":101,"name":"MOM_ACCELERATION","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":101,"name":"MOM_ACCELERATION","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":102,"name":"MOM_COMPOSITE","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":102,"name":"MOM_COMPOSITE","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":102,"name":"MOM_COMPOSITE","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":102,"name":"MOM_COMPOSITE","p1":0.0,"period":24,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":102,"name":"MOM_COMPOSITE","p1":0.0,"period":28,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":103,"name":"MOM_NORMALIZED_ROC","p1":0.0,"period":5,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":103,"name":"MOM_NORMALIZED_ROC","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":103,"name":"MOM_NORMALIZED_ROC","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":103,"name":"MOM_NORMALIZED_ROC","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":103,"name":"MOM_NORMALIZED_ROC","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":103,"name":"MOM_NORMALIZED_ROC","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","p1":0.0,"period":23,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","p1":0.0,"period":29,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":105,"name":"CROSS_EMA_SPREAD","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":105,"name":"CROSS_EMA_SPREAD","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":105,"name":"CROSS_EMA_SPREAD","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":105,"name":"CROSS_EMA_SPREAD","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":105,"name":"CROSS_EMA_SPREAD","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":105,"name":"CROSS_EMA_SPREAD","p1":0.0,"period":34,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":105,"name":"CROSS_EMA_SPREAD","p1":0.0,"period":38,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":106,"name":"CROSS_MOM_X_VOL","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":106,"name":"CROSS_MOM_X_VOL","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":106,"name":"CROSS_MOM_X_VOL","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":106,"name":"CROSS_MOM_X_VOL","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":106,"name":"CROSS_MOM_X_VOL","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":107,"name":"CROSS_VOL_ADJ_MOM","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":107,"name":"CROSS_VOL_ADJ_MOM","p1":0.0,"period":11,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":107,"name":"CROSS_VOL_ADJ_MOM","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":107,"name":"CROSS_VOL_ADJ_MOM","p1":0.0,"period":17,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":107,"name":"CROSS_VOL_ADJ_MOM","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":108,"name":"NORM_RETURN_ZSCORE","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":108,"name":"NORM_RETURN_ZSCORE","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":108,"name":"NORM_RETURN_ZSCORE","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":108,"name":"NORM_RETURN_ZSCORE","p1":0.0,"period":32,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":108,"name":"NORM_RETURN_ZSCORE","p1":0.0,"period":38,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":108,"name":"NORM_RETURN_ZSCORE","p1":0.0,"period":44,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":108,"name":"NORM_RETURN_ZSCORE","p1":0.0,"period":50,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":109,"name":"TIME_BARS_SINCE_HIGH","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":109,"name":"TIME_BARS_SINCE_HIGH","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":109,"name":"TIME_BARS_SINCE_HIGH","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":109,"name":"TIME_BARS_SINCE_HIGH","p1":0.0,"period":40,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":109,"name":"TIME_BARS_SINCE_HIGH","p1":0.0,"period":50,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":110,"name":"TIME_BARS_SINCE_LOW","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":110,"name":"TIME_BARS_SINCE_LOW","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":110,"name":"TIME_BARS_SINCE_LOW","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":110,"name":"TIME_BARS_SINCE_LOW","p1":0.0,"period":40,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":110,"name":"TIME_BARS_SINCE_LOW","p1":0.0,"period":50,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":116,"name":"REGIME_SKEWNESS","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":116,"name":"REGIME_SKEWNESS","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":116,"name":"REGIME_SKEWNESS","p1":0.0,"period":40,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":116,"name":"REGIME_SKEWNESS","p1":0.0,"period":50,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":116,"name":"REGIME_SKEWNESS","p1":0.0,"period":60,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":52,"name":"VOL_ATR_ZSCORE","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":52,"name":"VOL_ATR_ZSCORE","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":52,"name":"VOL_ATR_ZSCORE","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":52,"name":"VOL_ATR_ZSCORE","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":52,"name":"VOL_ATR_ZSCORE","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":59,"name":"VOL_RANGE_PCTILE","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":59,"name":"VOL_RANGE_PCTILE","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":59,"name":"VOL_RANGE_PCTILE","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":59,"name":"VOL_RANGE_PCTILE","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":59,"name":"VOL_RANGE_PCTILE","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":60,"name":"VOL_TR_MOMENTUM","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":60,"name":"VOL_TR_MOMENTUM","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":60,"name":"VOL_TR_MOMENTUM","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":60,"name":"VOL_TR_MOMENTUM","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":60,"name":"VOL_TR_MOMENTUM","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":70,"name":"ADX","p1":0.0,"period":10,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":70,"name":"ADX","p1":0.0,"period":12,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":70,"name":"ADX","p1":0.0,"period":14,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":70,"name":"ADX","p1":0.0,"period":16,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":70,"name":"ADX","p1":0.0,"period":18,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":70,"name":"ADX","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":71,"name":"AROON_UP","p1":0.0,"period":10,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":71,"name":"AROON_UP","p1":0.0,"period":14,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":71,"name":"AROON_UP","p1":0.0,"period":18,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":71,"name":"AROON_UP","p1":0.0,"period":22,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":71,"name":"AROON_UP","p1":0.0,"period":26,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":72,"name":"AROON_DOWN","p1":0.0,"period":10,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":72,"name":"AROON_DOWN","p1":0.0,"period":14,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":72,"name":"AROON_DOWN","p1":0.0,"period":18,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":72,"name":"AROON_DOWN","p1":0.0,"period":22,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":72,"name":"AROON_DOWN","p1":0.0,"period":26,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":73,"name":"LINREG_SLOPE","p1":0.0,"period":8,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":73,"name":"LINREG_SLOPE","p1":0.0,"period":11,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":73,"name":"LINREG_SLOPE","p1":0.0,"period":14,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":73,"name":"LINREG_SLOPE","p1":0.0,"period":17,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":73,"name":"LINREG_SLOPE","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":73,"name":"LINREG_SLOPE","p1":0.0,"period":23,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":73,"name":"LINREG_SLOPE","p1":0.0,"period":26,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":73,"name":"LINREG_SLOPE","p1":0.0,"period":29,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":74,"name":"LINREG_R2","p1":0.0,"period":8,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":74,"name":"LINREG_R2","p1":0.0,"period":11,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":74,"name":"LINREG_R2","p1":0.0,"period":14,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":74,"name":"LINREG_R2","p1":0.0,"period":17,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":74,"name":"LINREG_R2","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":74,"name":"LINREG_R2","p1":0.0,"period":23,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":74,"name":"LINREG_R2","p1":0.0,"period":26,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":74,"name":"LINREG_R2","p1":0.0,"period":29,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":75,"name":"EFFICIENCY","p1":0.0,"period":8,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":75,"name":"EFFICIENCY","p1":0.0,"period":11,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":75,"name":"EFFICIENCY","p1":0.0,"period":14,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":75,"name":"EFFICIENCY","p1":0.0,"period":17,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":75,"name":"EFFICIENCY","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":75,"name":"EFFICIENCY","p1":0.0,"period":23,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":75,"name":"EFFICIENCY","p1":0.0,"period":26,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":75,"name":"EFFICIENCY","p1":0.0,"period":29,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":76,"name":"ANGLE","p1":0.0,"period":8,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":76,"name":"ANGLE","p1":0.0,"period":11,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":76,"name":"ANGLE","p1":0.0,"period":14,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":76,"name":"ANGLE","p1":0.0,"period":17,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":76,"name":"ANGLE","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":76,"name":"ANGLE","p1":0.0,"period":23,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":76,"name":"ANGLE","p1":0.0,"period":26,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":76,"name":"ANGLE","p1":0.0,"period":29,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":77,"name":"DURATION","p1":0.0,"period":1,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":78,"name":"HURST","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":78,"name":"HURST","p1":0.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":78,"name":"HURST","p1":0.0,"period":40,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":78,"name":"HURST","p1":0.0,"period":50,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":78,"name":"HURST","p1":0.0,"period":60,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":80,"name":"FRACTAL_DIM","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":80,"name":"FRACTAL_DIM","p1":0.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":80,"name":"FRACTAL_DIM","p1":0.0,"period":40,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":80,"name":"FRACTAL_DIM","p1":0.0,"period":50,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":80,"name":"FRACTAL_DIM","p1":0.0,"period":60,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":81,"name":"TREND_PERSIST","p1":0.0,"period":10,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":81,"name":"TREND_PERSIST","p1":0.0,"period":15,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":81,"name":"TREND_PERSIST","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":81,"name":"TREND_PERSIST","p1":0.0,"period":25,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":81,"name":"TREND_PERSIST","p1":0.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":83,"name":"MICRO_TREND_STRUCT","p1":0.0,"period":5,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":83,"name":"MICRO_TREND_STRUCT","p1":0.0,"period":8,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":83,"name":"MICRO_TREND_STRUCT","p1":0.0,"period":11,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":83,"name":"MICRO_TREND_STRUCT","p1":0.0,"period":14,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":83,"name":"MICRO_TREND_STRUCT","p1":0.0,"period":17,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":83,"name":"MICRO_TREND_STRUCT","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":2.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":4.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":8.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":2.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":4.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":8.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":2.0,"period":40,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":4.0,"period":40,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":8.0,"period":40,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":2.0,"period":50,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":4.0,"period":50,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":8.0,"period":50,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":2.0,"period":60,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":4.0,"period":60,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":79,"name":"ID_79","p1":8.0,"period":60,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":1.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":3.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":5.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":1.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":3.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":5.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":1.0,"period":40,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":3.0,"period":40,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":5.0,"period":40,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":1.0,"period":50,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":3.0,"period":50,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":82,"name":"ID_82","p1":5.0,"period":50,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":50,"name":"ID_50","p1":0.0,"period":8,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":50,"name":"ID_50","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":50,"name":"ID_50","p1":0.0,"period":12,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":50,"name":"ID_50","p1":0.0,"period":14,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":50,"name":"ID_50","p1":0.0,"period":16,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":50,"name":"ID_50","p1":0.0,"period":18,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":50,"name":"ID_50","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":51,"name":"ID_51","p1":0.0,"period":8,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":51,"name":"ID_51","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":51,"name":"ID_51","p1":0.0,"period":12,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":51,"name":"ID_51","p1":0.0,"period":14,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":51,"name":"ID_51","p1":0.0,"period":16,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":51,"name":"ID_51","p1":0.0,"period":18,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":51,"name":"ID_51","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":53,"name":"ID_53","p1":0.0,"period":14,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":53,"name":"ID_53","p1":0.0,"period":18,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":53,"name":"ID_53","p1":0.0,"period":22,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":53,"name":"ID_53","p1":0.0,"period":26,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":53,"name":"ID_53","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":54,"name":"ID_54","p1":0.0,"period":14,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":54,"name":"ID_54","p1":0.0,"period":18,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":54,"name":"ID_54","p1":0.0,"period":22,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":54,"name":"ID_54","p1":0.0,"period":26,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":54,"name":"ID_54","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":55,"name":"ID_55","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":55,"name":"ID_55","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":55,"name":"ID_55","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":55,"name":"ID_55","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":55,"name":"ID_55","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":56,"name":"ID_56","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":56,"name":"ID_56","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":56,"name":"ID_56","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":56,"name":"ID_56","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":56,"name":"ID_56","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":57,"name":"ID_57","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":57,"name":"ID_57","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":57,"name":"ID_57","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":57,"name":"ID_57","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":57,"name":"ID_57","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":58,"name":"ID_58","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":58,"name":"ID_58","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":58,"name":"ID_58","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":58,"name":"ID_58","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":58,"name":"ID_58","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":61,"name":"ID_61","p1":0.0,"period":14,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":61,"name":"ID_61","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":61,"name":"ID_61","p1":0.0,"period":26,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":61,"name":"ID_61","p1":0.0,"period":32,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":61,"name":"ID_61","p1":0.0,"period":38,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":61,"name":"ID_61","p1":0.0,"period":44,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":61,"name":"ID_61","p1":0.0,"period":50,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":63,"name":"ID_63","p1":0.0,"period":5,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":63,"name":"ID_63","p1":0.0,"period":8,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":63,"name":"ID_63","p1":0.0,"period":11,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":63,"name":"ID_63","p1":0.0,"period":14,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":63,"name":"ID_63","p1":0.0,"period":17,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":63,"name":"ID_63","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":111,"name":"ID_111","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":111,"name":"ID_111","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":111,"name":"ID_111","p1":0.0,"period":40,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":111,"name":"ID_111","p1":0.0,"period":50,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":111,"name":"ID_111","p1":0.0,"period":60,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":112,"name":"ID_112","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":112,"name":"ID_112","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":112,"name":"ID_112","p1":0.0,"period":40,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":112,"name":"ID_112","p1":0.0,"period":50,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":112,"name":"ID_112","p1":0.0,"period":60,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":113,"name":"ID_113","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":113,"name":"ID_113","p1":0.0,"period":40,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":113,"name":"ID_113","p1":0.0,"period":50,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":113,"name":"ID_113","p1":0.0,"period":60,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":115,"name":"ID_115","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":115,"name":"ID_115","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":115,"name":"ID_115","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":115,"name":"ID_115","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":115,"name":"ID_115","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"index_position_causal","indicator_id":118,"name":"ID_118","p1":0.0,"period":1,"role":"filter","source_semantics":"source derives a deterministic cycle from the row index; it does not read future rows","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":119,"name":"ID_119","p1":0.0,"period":1,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":62,"name":"ID_62","p1":0.0,"period":10,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":62,"name":"ID_62","p1":0.0,"period":15,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":62,"name":"ID_62","p1":0.0,"period":20,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":62,"name":"ID_62","p1":0.0,"period":25,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":62,"name":"ID_62","p1":0.0,"period":30,"role":"trend","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"index_position_causal","indicator_id":117,"name":"ID_117","p1":0.0,"period":1,"role":"trend","source_semantics":"source derives a deterministic cycle from the row index; it does not read future rows","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":10.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":20.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":50.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":10.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":20.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":50.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":10.0,"period":40,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":20.0,"period":40,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":50.0,"period":40,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":10.0,"period":50,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":20.0,"period":50,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":114,"name":"ID_114","p1":50.0,"period":50,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":60,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":90,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":120,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":150,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":180,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":210,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":240,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":270,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":300,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":330,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":120,"name":"ID_120","p1":0.0,"period":360,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":60,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":90,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":120,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":150,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":180,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":210,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":240,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":270,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":300,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":330,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":121,"name":"ID_121","p1":0.0,"period":360,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":60,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":90,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":120,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":150,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":180,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":210,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":240,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":270,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":300,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":330,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":122,"name":"ID_122","p1":0.0,"period":360,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":60,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":90,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":120,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":150,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":180,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":210,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":240,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":270,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":300,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":330,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":123,"name":"ID_123","p1":0.0,"period":360,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":60,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":90,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":120,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":150,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":180,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":210,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":240,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":270,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":300,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":330,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":124,"name":"ID_124","p1":0.0,"period":360,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":60,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":90,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":120,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":150,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":180,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":210,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":240,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":270,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":300,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":330,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":125,"name":"ID_125","p1":0.0,"period":360,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":60,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":90,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":120,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":150,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":180,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":210,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":240,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":270,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":300,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":330,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":126,"name":"ID_126","p1":0.0,"period":360,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":127,"name":"ID_127","p1":0.0,"period":10,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":127,"name":"ID_127","p1":0.0,"period":15,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":127,"name":"ID_127","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":127,"name":"ID_127","p1":0.0,"period":25,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":127,"name":"ID_127","p1":0.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":127,"name":"ID_127","p1":0.0,"period":35,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":127,"name":"ID_127","p1":0.0,"period":40,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":1.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":1.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":1.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":1.5,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.5,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":1.5,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":128,"name":"ID_128","p1":2.5,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":1.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.5,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":1.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.0,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.5,"period":18,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":1.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.0,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.5,"period":22,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":1.5,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.5,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":1.5,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.0,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":129,"name":"ID_129","p1":2.5,"period":30,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":130,"name":"ID_130","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":130,"name":"ID_130","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":130,"name":"ID_130","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":130,"name":"ID_130","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":130,"name":"ID_130","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":131,"name":"ID_131","p1":0.0,"period":14,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":131,"name":"ID_131","p1":0.0,"period":20,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":131,"name":"ID_131","p1":0.0,"period":26,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":131,"name":"ID_131","p1":0.0,"period":32,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":131,"name":"ID_131","p1":0.0,"period":38,"role":"level","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":135,"name":"ID_135","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":135,"name":"ID_135","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":135,"name":"ID_135","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":135,"name":"ID_135","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":135,"name":"ID_135","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":136,"name":"ID_136","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":136,"name":"ID_136","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":136,"name":"ID_136","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":136,"name":"ID_136","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":136,"name":"ID_136","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":137,"name":"ID_137","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":137,"name":"ID_137","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":137,"name":"ID_137","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":137,"name":"ID_137","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":137,"name":"ID_137","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":138,"name":"ID_138","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":138,"name":"ID_138","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":138,"name":"ID_138","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":139,"name":"ID_139","p1":0.0,"period":1,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":140,"name":"ID_140","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":140,"name":"ID_140","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":140,"name":"ID_140","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":141,"name":"ID_141","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":141,"name":"ID_141","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":141,"name":"ID_141","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":141,"name":"ID_141","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":141,"name":"ID_141","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":142,"name":"ID_142","p1":0.0,"period":1,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":143,"name":"ID_143","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":143,"name":"ID_143","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":143,"name":"ID_143","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":143,"name":"ID_143","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":143,"name":"ID_143","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":144,"name":"ID_144","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":144,"name":"ID_144","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":144,"name":"ID_144","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":144,"name":"ID_144","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":144,"name":"ID_144","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":145,"name":"ID_145","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":145,"name":"ID_145","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":145,"name":"ID_145","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":145,"name":"ID_145","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":145,"name":"ID_145","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":146,"name":"ID_146","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":146,"name":"ID_146","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":146,"name":"ID_146","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":146,"name":"ID_146","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":146,"name":"ID_146","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":147,"name":"ID_147","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":147,"name":"ID_147","p1":0.0,"period":15,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":147,"name":"ID_147","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":147,"name":"ID_147","p1":0.0,"period":25,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":147,"name":"ID_147","p1":0.0,"period":30,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":150,"name":"ID_150","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":150,"name":"ID_150","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":150,"name":"ID_150","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":150,"name":"ID_150","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":150,"name":"ID_150","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":151,"name":"ID_151","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":151,"name":"ID_151","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":151,"name":"ID_151","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":151,"name":"ID_151","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":151,"name":"ID_151","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":152,"name":"ID_152","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":152,"name":"ID_152","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"validated"},{"causal_classification":"trailing_window_causal","indicator_id":152,"name":"ID_152","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":152,"name":"ID_152","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":152,"name":"ID_152","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":153,"name":"ID_153","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":153,"name":"ID_153","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":153,"name":"ID_153","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":153,"name":"ID_153","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":153,"name":"ID_153","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":154,"name":"ID_154","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":154,"name":"ID_154","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":154,"name":"ID_154","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":155,"name":"ID_155","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":155,"name":"ID_155","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":155,"name":"ID_155","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":155,"name":"ID_155","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":155,"name":"ID_155","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":156,"name":"ID_156","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":156,"name":"ID_156","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":156,"name":"ID_156","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":156,"name":"ID_156","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":156,"name":"ID_156","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":157,"name":"ID_157","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":157,"name":"ID_157","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":157,"name":"ID_157","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":157,"name":"ID_157","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":157,"name":"ID_157","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":158,"name":"ID_158","p1":0.0,"period":10,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":158,"name":"ID_158","p1":0.0,"period":15,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":158,"name":"ID_158","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":158,"name":"ID_158","p1":0.0,"period":25,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":158,"name":"ID_158","p1":0.0,"period":30,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":160,"name":"ID_160","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":160,"name":"ID_160","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":160,"name":"ID_160","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":160,"name":"ID_160","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":160,"name":"ID_160","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":160,"name":"ID_160","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":160,"name":"ID_160","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":161,"name":"ID_161","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":161,"name":"ID_161","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":161,"name":"ID_161","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":161,"name":"ID_161","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":161,"name":"ID_161","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":161,"name":"ID_161","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":161,"name":"ID_161","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":5.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":10.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":5.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":10.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":5.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":10.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":5.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":10.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":5.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":10.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":5.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":162,"name":"ID_162","p1":10.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":163,"name":"ID_163","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":163,"name":"ID_163","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":163,"name":"ID_163","p1":0.0,"period":24,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":163,"name":"ID_163","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":163,"name":"ID_163","p1":0.0,"period":28,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":164,"name":"ID_164","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":164,"name":"ID_164","p1":0.0,"period":22,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":164,"name":"ID_164","p1":0.0,"period":24,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":164,"name":"ID_164","p1":0.0,"period":26,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":164,"name":"ID_164","p1":0.0,"period":28,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":165,"name":"ID_165","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":165,"name":"ID_165","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":165,"name":"ID_165","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":165,"name":"ID_165","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":165,"name":"ID_165","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":165,"name":"ID_165","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":165,"name":"ID_165","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":166,"name":"ID_166","p1":0.0,"period":8,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":166,"name":"ID_166","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":166,"name":"ID_166","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":166,"name":"ID_166","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":166,"name":"ID_166","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":166,"name":"ID_166","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":166,"name":"ID_166","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":167,"name":"ID_167","p1":0.0,"period":10,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":167,"name":"ID_167","p1":0.0,"period":12,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":167,"name":"ID_167","p1":0.0,"period":14,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":167,"name":"ID_167","p1":0.0,"period":16,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":167,"name":"ID_167","p1":0.0,"period":18,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":167,"name":"ID_167","p1":0.0,"period":20,"role":"osc","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":168,"name":"ID_168","p1":0.0,"period":5,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":168,"name":"ID_168","p1":0.0,"period":8,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":168,"name":"ID_168","p1":0.0,"period":11,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":168,"name":"ID_168","p1":0.0,"period":14,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":168,"name":"ID_168","p1":0.0,"period":17,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"},{"causal_classification":"trailing_window_causal","indicator_id":168,"name":"ID_168","p1":0.0,"period":20,"role":"filter","source_semantics":"source reads the current row and preceding rows only; completed-bar availability remains required","support_state":"source_implemented_unvalidated"}],"implementation_coverage":{"coverage":"80 of 1107","historical_registered_variants":1107,"validated_distinct_formula_variants":80},"schema_version":1,"source":"Artifex historical registry; source-semantics audit only","support_states":["validated","source_implemented_unvalidated","alias_refused","unregistered"]} diff --git a/control_plane/trading_studio/indicators/historical_band_channel.py b/control_plane/trading_studio/indicators/historical_band_channel.py new file mode 100644 index 0000000..40b23ca --- /dev/null +++ b/control_plane/trading_studio/indicators/historical_band_channel.py @@ -0,0 +1,267 @@ +"""Native Batch01 port of observed historical band/channel formulas. + +This module is intentionally limited to the exact parameter triples observed in +the frozen engineering map. Oracle parity remains the gate for production +feature-catalog validation. +""" + +from __future__ import annotations + +import math +from collections.abc import Callable +from itertools import product + +import numpy as np + +NativeEvaluator = Callable[[np.ndarray, np.ndarray, np.ndarray, np.ndarray, int, float], np.ndarray] + + +def _sma(values: np.ndarray, period: int) -> np.ndarray: + out = np.full(len(values), np.nan) + if len(values) < period: + return out + total = sum(values[:period]) + out[period - 1] = total / period + for index in range(period, len(values)): + total += values[index] - values[index - period] + out[index] = total / period + return out + + +def _ema(values: np.ndarray, period: int) -> np.ndarray: + out = np.full(len(values), np.nan) + if len(values) < period: + return out + alpha = 2.0 / (period + 1) + out[period - 1] = sum(values[:period]) / period + for index in range(period, len(values)): + out[index] = alpha * values[index] + (1 - alpha) * out[index - 1] + return out + + +def _rma(values: np.ndarray, period: int) -> np.ndarray: + out = np.full(len(values), np.nan) + total = 0.0 + count = 0 + start = -1 + for index, value in enumerate(values): + if not np.isnan(value): + total += value + count += 1 + if count == period: + start = index + break + if start < 0: + return out + out[start] = total / period + alpha = 1.0 / period + for index in range(start + 1, len(values)): + out[index] = ( + out[index - 1] + if np.isnan(values[index]) + else alpha * values[index] + (1 - alpha) * out[index - 1] + ) + return out + + +def _true_range(high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: + out = np.empty(len(close)) + out[0] = high[0] - low[0] + for index in range(1, len(close)): + out[index] = max( + high[index] - low[index], + abs(high[index] - close[index - 1]), + abs(low[index] - close[index - 1]), + ) + return out + + +def _atr(close: np.ndarray, high: np.ndarray, low: np.ndarray, period: int) -> np.ndarray: + return _rma(_true_range(high, low, close), period) + + +def bb_upper( + close: np.ndarray, high: np.ndarray, low: np.ndarray, volume: np.ndarray, period: int, p1: float +) -> np.ndarray: + multiplier = p1 if p1 > 0 else 2.0 + average = _sma(close, period) + out = np.full(len(close), np.nan) + for index in range(period - 1, len(close)): + variance = sum( + (close[item] - average[index]) ** 2 for item in range(index - period + 1, index + 1) + ) + out[index] = average[index] + multiplier * math.sqrt(variance / (period - 1)) + return out + + +def bb_lower( + close: np.ndarray, high: np.ndarray, low: np.ndarray, volume: np.ndarray, period: int, p1: float +) -> np.ndarray: + multiplier = p1 if p1 > 0 else 2.0 + average = _sma(close, period) + out = np.full(len(close), np.nan) + for index in range(period - 1, len(close)): + variance = sum( + (close[item] - average[index]) ** 2 for item in range(index - period + 1, index + 1) + ) + out[index] = average[index] - multiplier * math.sqrt(variance / (period - 1)) + return out + + +def supertrend( + close: np.ndarray, high: np.ndarray, low: np.ndarray, volume: np.ndarray, period: int, p1: float +) -> np.ndarray: + multiplier = p1 if p1 > 0 else 3.0 + atr = _rma(_true_range(high, low, close), period) + out = np.full(len(close), np.nan) + upper = np.full(len(close), np.nan) + lower = np.full(len(close), np.nan) + direction = np.ones(len(close)) + for index in range(period, len(close)): + if np.isnan(atr[index]): + continue + midpoint = (high[index] + low[index]) / 2.0 + basic_upper = midpoint + multiplier * atr[index] + basic_lower = midpoint - multiplier * atr[index] + if index == period: + upper[index], lower[index] = basic_upper, basic_lower + out[index] = lower[index] if close[index] > lower[index] else upper[index] + direction[index] = 1.0 if close[index] > out[index] else -1.0 + continue + upper[index] = ( + min(basic_upper, upper[index - 1]) + if not np.isnan(upper[index - 1]) and close[index - 1] <= upper[index - 1] + else basic_upper + ) + lower[index] = ( + max(basic_lower, lower[index - 1]) + if not np.isnan(lower[index - 1]) and close[index - 1] >= lower[index - 1] + else basic_lower + ) + if direction[index - 1] == 1.0: + out[index] = lower[index] if close[index] >= lower[index] else upper[index] + else: + out[index] = upper[index] if close[index] <= upper[index] else lower[index] + direction[index] = 1.0 if close[index] > out[index] else -1.0 + return out + + +def donch_upper( + close: np.ndarray, high: np.ndarray, low: np.ndarray, volume: np.ndarray, period: int, p1: float +) -> np.ndarray: + out = np.full(len(high), np.nan) + for index in range(period - 1, len(high)): + out[index] = max(high[index - period + 1 : index + 1]) + return out + + +def donch_lower( + close: np.ndarray, high: np.ndarray, low: np.ndarray, volume: np.ndarray, period: int, p1: float +) -> np.ndarray: + out = np.full(len(low), np.nan) + for index in range(period - 1, len(low)): + out[index] = min(low[index - period + 1 : index + 1]) + return out + + +def kelt_upper( + close: np.ndarray, high: np.ndarray, low: np.ndarray, volume: np.ndarray, period: int, p1: float +) -> np.ndarray: + multiplier = p1 if p1 > 0 else 1.5 + basis = _ema(close, period) + atr = _atr(close, high, low, period) + out = np.full(len(close), np.nan) + valid = ~np.isnan(basis) & ~np.isnan(atr) + out[valid] = basis[valid] + multiplier * atr[valid] + return out + + +def kelt_lower( + close: np.ndarray, high: np.ndarray, low: np.ndarray, volume: np.ndarray, period: int, p1: float +) -> np.ndarray: + multiplier = p1 if p1 > 0 else 1.5 + basis = _ema(close, period) + atr = _atr(close, high, low, period) + out = np.full(len(close), np.nan) + valid = ~np.isnan(basis) & ~np.isnan(atr) + out[valid] = basis[valid] - multiplier * atr[valid] + return out + + +def psar( + close: np.ndarray, high: np.ndarray, low: np.ndarray, volume: np.ndarray, period: int, p1: float +) -> np.ndarray: + acceleration_step = p1 if p1 > 0 else 0.02 + out = np.full(len(close), np.nan) + if len(close) < 2: + return out + bullish, acceleration, acceleration_maximum = True, 0.02, 0.2 + extreme, sar = high[0], low[0] + for index in range(1, len(close)): + previous_sar = sar + sar = previous_sar + acceleration * (extreme - previous_sar) + if bullish: + sar = min(sar, low[index - 1]) + if index >= 2: + sar = min(sar, low[index - 2]) + if low[index] < sar: + bullish, sar, extreme, acceleration = False, extreme, low[index], 0.02 + elif high[index] > extreme: + extreme = high[index] + acceleration = min(acceleration + acceleration_step, acceleration_maximum) + else: + sar = max(sar, high[index - 1]) + if index >= 2: + sar = max(sar, high[index - 2]) + if high[index] > sar: + bullish, sar, extreme, acceleration = True, extreme, high[index], 0.02 + elif low[index] < extreme: + extreme = low[index] + acceleration = min(acceleration + acceleration_step, acceleration_maximum) + out[index] = sar + return out + + +_BOLLINGER = tuple(product((14, 16, 18, 20, 22, 24), (1.5, 2.0, 2.5))) +_KELTNER = tuple(product((14, 16, 18, 20, 22, 24), (1.0, 1.5, 2.0))) +OBSERVED_BAND_CHANNEL_PARAMS = frozenset( + (indicator_id, period, p1) + for indicator_id, params in ( + (17, _BOLLINGER), + (18, _BOLLINGER), + (19, product((8, 10, 12, 14), (2.0, 3.0, 4.0))), + (20, ((period, 0.0) for period in (10, 14, 18, 22, 26))), + (21, ((period, 0.0) for period in (10, 14, 18, 22, 26))), + (23, _KELTNER), + (24, _KELTNER), + (28, ((1, p1) for p1 in (0.01, 0.02, 0.03))), + ) + for period, p1 in params +) + +NATIVE_EVALUATORS: dict[int, NativeEvaluator] = { + 17: bb_upper, + 18: bb_lower, + 19: supertrend, + 20: donch_upper, + 21: donch_lower, + 23: kelt_upper, + 24: kelt_lower, + 28: psar, +} + + +def evaluate_band_channel( + indicator_id: int, + close: np.ndarray, + high: np.ndarray, + low: np.ndarray, + volume: np.ndarray, + period: int, + p1: float, +) -> np.ndarray: + """Evaluate one exact Batch01 observed primitive, refusing grid expansion.""" + key = indicator_id, period, p1 + if key not in OBSERVED_BAND_CHANNEL_PARAMS: + raise ValueError(f"unsupported Batch01 band_channel variant: {indicator_id}:{period}:{p1}") + return NATIVE_EVALUATORS[indicator_id](close, high, low, volume, period, p1) diff --git a/control_plane/trading_studio/indicators/historical_formulae.py b/control_plane/trading_studio/indicators/historical_formulae.py new file mode 100644 index 0000000..c9bce72 --- /dev/null +++ b/control_plane/trading_studio/indicators/historical_formulae.py @@ -0,0 +1,2391 @@ +""" +Indicator functions extracted from notebooks/gpu_search.py (lines 104-2626). +Contains: signal_color, all ~120 indicator functions, compute_indicator dispatcher. +Self-contained — imports only numpy, numba, math. + +DO NOT EDIT — regenerate from gpu_search.py if indicators change. +""" +import math +import numpy as np +import numba as nb + + +# CORE HELPERS +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def _sma(values, period): + n = len(values); out = np.full(n, np.nan) + if n < period: return out + s = 0.0 + for j in range(period): s += values[j] + out[period - 1] = s / period + for i in range(period, n): + s += values[i] - values[i - period] + out[i] = s / period + return out + +@nb.njit(cache=True) +def _ema(values, period): + n = len(values); out = np.full(n, np.nan) + if n < period: return out + alpha = 2.0 / (period + 1) + s = 0.0 + for j in range(period): s += values[j] + out[period - 1] = s / period + for i in range(period, n): + out[i] = alpha * values[i] + (1 - alpha) * out[i - 1] + return out + +@nb.njit(cache=True) +def _wma(values, period): + n = len(values); out = np.full(n, np.nan) + if n < period: return out + w_sum = period * (period + 1) / 2.0 + for i in range(period - 1, n): + s = 0.0 + for j in range(period): + s += values[i - period + 1 + j] * (j + 1) + out[i] = s / w_sum + return out + +@nb.njit(cache=True) +def _rma(values, period): + n = len(values); out = np.full(n, np.nan) + if n < period: return out + s = 0.0; cnt = 0; start = -1 + for i in range(n): + if not np.isnan(values[i]): + s += values[i]; cnt += 1 + if cnt == period: start = i; break + if start < 0: return out + out[start] = s / period + alpha = 1.0 / period + for i in range(start + 1, n): + if np.isnan(values[i]): out[i] = out[i - 1] + else: out[i] = alpha * values[i] + (1 - alpha) * out[i - 1] + return out + +@nb.njit(cache=True) +def _true_range(high, low, close): + n = len(close); tr = np.empty(n) + tr[0] = high[0] - low[0] + for i in range(1, n): + hl = high[i] - low[i] + hc = abs(high[i] - close[i - 1]) + lc = abs(low[i] - close[i - 1]) + tr[i] = max(hl, max(hc, lc)) + return tr + +@nb.njit(cache=True) +def _atr(close, high, low, period): + tr = _true_range(high, low, close) + return _rma(tr, period) + +# ═══════════════════════════════════════════════════════════════════════════ +# SIGNAL COLOR +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def signal_color(values): + """1=BLUE(up), -1=RED(down), 0=NaN.""" + n = len(values) + c = np.zeros(n, dtype=nb.int8) + prev = nb.int8(0) + for i in range(1, n): + if np.isnan(values[i]) or np.isnan(values[i - 1]): + c[i] = 0; prev = 0 + elif values[i] > values[i - 1]: + c[i] = 1; prev = 1 + elif values[i] < values[i - 1]: + c[i] = -1; prev = -1 + else: + c[i] = prev + return c + +# ═══════════════════════════════════════════════════════════════════════════ +# MOVING AVERAGES (IDs 0-16) +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def ma_sma(close, period, p1): + return _sma(close, period) + +@nb.njit(cache=True) +def ma_ema(close, period, p1): + return _ema(close, period) + +@nb.njit(cache=True) +def ma_wma(close, period, p1): + return _wma(close, period) + +@nb.njit(cache=True) +def ma_hma(close, period, p1): + half = max(period // 2, 1) + sqrt_p = max(int(round(math.sqrt(period))), 1) + wh = _wma(close, half); wf = _wma(close, period) + n = len(close); diff = np.full(n, np.nan) + for i in range(n): + if not np.isnan(wh[i]) and not np.isnan(wf[i]): + diff[i] = 2.0 * wh[i] - wf[i] + return _wma(diff, sqrt_p) + +@nb.njit(cache=True) +def ma_dema(close, period, p1): + e1 = _ema(close, period); n = len(close) + start = -1 + for i in range(n): + if not np.isnan(e1[i]): start = i; break + if start < 0: return np.full(n, np.nan) + e2_raw = _ema(e1[start:], period) + e2 = np.full(n, np.nan) + for i in range(len(e2_raw)): e2[start + i] = e2_raw[i] + out = np.full(n, np.nan) + for i in range(n): + if not np.isnan(e1[i]) and not np.isnan(e2[i]): + out[i] = 2.0 * e1[i] - e2[i] + return out + +@nb.njit(cache=True) +def ma_tema(close, period, p1): + e1 = _ema(close, period); n = len(close) + s1 = -1 + for i in range(n): + if not np.isnan(e1[i]): s1 = i; break + if s1 < 0: return np.full(n, np.nan) + e2_raw = _ema(e1[s1:], period) + s2 = -1 + for i in range(len(e2_raw)): + if not np.isnan(e2_raw[i]): s2 = i; break + if s2 < 0: return np.full(n, np.nan) + e3_raw = _ema(e2_raw[s2:], period) + e2 = np.full(n, np.nan); e3 = np.full(n, np.nan) + for i in range(len(e2_raw)): e2[s1 + i] = e2_raw[i] + for i in range(len(e3_raw)): e3[s1 + s2 + i] = e3_raw[i] + out = np.full(n, np.nan) + for i in range(n): + if not np.isnan(e1[i]) and not np.isnan(e2[i]) and not np.isnan(e3[i]): + out[i] = 3.0 * e1[i] - 3.0 * e2[i] + e3[i] + return out + +@nb.njit(cache=True) +def ma_kama(close, period, p1): + n = len(close); out = np.full(n, np.nan) + if n < period: return out + fast_sc = 2.0 / 3.0; slow_sc = 2.0 / 31.0 + s = 0.0 + for j in range(period): s += close[j] + out[period - 1] = s / period + for i in range(period, n): + d = abs(close[i] - close[i - period]) + v = 0.0 + for j in range(i - period + 1, i + 1): v += abs(close[j] - close[j - 1]) + er = d / v if v > 0 else 0.0 + sc = (er * (fast_sc - slow_sc) + slow_sc) ** 2 + out[i] = out[i - 1] + sc * (close[i] - out[i - 1]) + return out + +@nb.njit(cache=True) +def ma_ehlers_ss(close, period, p1): + n = len(close); out = np.full(n, np.nan) + if n < 3: return out + a = math.exp(-math.sqrt(2.0) * math.pi / period) + b = 2.0 * a * math.cos(math.sqrt(2.0) * math.pi / period) + c2 = b; c3 = -(a * a); c1 = 1.0 - c2 - c3 + out[0] = close[0]; out[1] = close[1] + for i in range(2, n): + out[i] = c1 * (close[i] + close[i - 1]) / 2.0 + c2 * out[i - 1] + c3 * out[i - 2] + return out + +@nb.njit(cache=True) +def ma_mcginley(close, period, p1): + n = len(close); out = np.full(n, np.nan) + out[0] = close[0] + for i in range(1, n): + if out[i - 1] == 0: out[i] = close[i] + else: + r = close[i] / out[i - 1] + d = period * (r ** 4) + out[i] = out[i - 1] + (close[i] - out[i - 1]) / d if d != 0 else close[i] + out[:period] = np.nan + return out + +@nb.njit(cache=True) +def ma_jma(close, period, p1): + n = len(close) + pb = max(-0.5, min(2.5, p1 / 100.0 + 1.5)) + beta = 0.45 * (period - 1) / (0.45 * (period - 1) + 2.0) + alpha = beta ** 3 + e0 = np.zeros(n); e1 = np.zeros(n); e2 = np.zeros(n); jma = np.zeros(n) + e0[0] = close[0]; jma[0] = close[0] + for i in range(1, n): + e0[i] = (1 - alpha) * close[i] + alpha * e0[i - 1] + e1[i] = (close[i] - e0[i]) * (1 - beta) + beta * e1[i - 1] + e2[i] = (e0[i] + pb * e1[i] - jma[i - 1]) * (1 - alpha) ** 2 + alpha ** 2 * e2[i - 1] + jma[i] = jma[i - 1] + e2[i] + out = jma.copy(); out[:period] = np.nan + return out + +@nb.njit(cache=True) +def ma_t3(close, period, p1): + v = p1 + c1 = -(v ** 3); c2 = 3*v**2 + 3*v**3; c3 = -6*v**2 - 3*v - 3*v**3; c4 = 1 + 3*v + v**3 + 3*v**2 + n = len(close) + e1 = _ema(close, period) + fv = close[0] + for i in range(n): + if not np.isnan(e1[i]): fv = e1[i]; break + t = np.empty(n) + for i in range(n): t[i] = e1[i] if not np.isnan(e1[i]) else fv + e2 = _ema(t, period) + for i in range(n): t[i] = e2[i] if not np.isnan(e2[i]) else fv + e3 = _ema(t, period) + for i in range(n): t[i] = e3[i] if not np.isnan(e3[i]) else fv + e4 = _ema(t, period) + for i in range(n): t[i] = e4[i] if not np.isnan(e4[i]) else fv + e5 = _ema(t, period) + for i in range(n): t[i] = e5[i] if not np.isnan(e5[i]) else fv + e6 = _ema(t, period) + out = np.full(n, np.nan) + warmup = 6 * (period - 1) + for i in range(warmup, n): + out[i] = c1 * e6[i] + c2 * e5[i] + c3 * e4[i] + c4 * e3[i] + return out + +@nb.njit(cache=True) +def ma_alma(close, period, p1): + offset = 0.85; sigma = p1 if p1 > 0 else 6.0 + n = len(close); out = np.full(n, np.nan) + if n < period: return out + m = offset * (period - 1); s = period / sigma + w = np.empty(period); ws = 0.0 + for j in range(period): + w[j] = math.exp(-((j - m) ** 2) / (2 * s * s)); ws += w[j] + for i in range(period - 1, n): + v = 0.0 + for j in range(period): v += close[i - period + 1 + j] * w[j] + out[i] = v / ws + return out + +@nb.njit(cache=True) +def ma_zlema(close, period, p1): + lag = (period - 1) // 2; n = len(close) + adj = np.empty(n) + for i in range(lag): adj[i] = close[i] + for i in range(lag, n): adj[i] = close[i] + (close[i] - close[i - lag]) + return _ema(adj, period) + +@nb.njit(cache=True) +def ma_vidya(close, period, p1): + n = len(close); out = np.full(n, np.nan) + if n < period: return out + alpha = 2.0 / (period + 1) + s = 0.0 + for j in range(period): s += close[j] + out[period - 1] = s / period + for i in range(period, n): + ups = 0.0; dns = 0.0 + for j in range(i - period + 1, i + 1): + d = close[j] - close[j - 1] + if d > 0: ups += d + else: dns -= d + cmo = abs(ups - dns) / (ups + dns) if (ups + dns) > 0 else 0.0 + out[i] = alpha * cmo * close[i] + (1 - alpha * cmo) * out[i - 1] + return out + +@nb.njit(cache=True) +def ma_frama(close, period, p1): + n = len(close); out = np.full(n, np.nan) + if n < period: return out + half = period // 2 + s = 0.0 + for j in range(period): s += close[j] + out[period - 1] = s / period + for i in range(period, n): + h1_max = -1e18; h1_min = 1e18 + for j in range(i - period + 1, i - half + 1): + if close[j] > h1_max: h1_max = close[j] + if close[j] < h1_min: h1_min = close[j] + h2_max = -1e18; h2_min = 1e18 + for j in range(i - half + 1, i + 1): + if close[j] > h2_max: h2_max = close[j] + if close[j] < h2_min: h2_min = close[j] + h3_max = -1e18; h3_min = 1e18 + for j in range(i - period + 1, i + 1): + if close[j] > h3_max: h3_max = close[j] + if close[j] < h3_min: h3_min = close[j] + h1 = h1_max - h1_min; h2 = h2_max - h2_min; h3 = h3_max - h3_min + n1 = (h1 + h2) / h3 if h3 > 0 else 1.0 + dim = math.log(max(n1, 1e-10)) / math.log(2.0) if n1 > 0 else 1.0 + af = math.exp(-4.6 * (dim - 1.0)) + af = max(0.01, min(1.0, af)) + out[i] = af * close[i] + (1 - af) * out[i - 1] + return out + +@nb.njit(cache=True) +def ma_lsma(close, period, p1): + n = len(close); out = np.full(n, np.nan) + if n < period: return out + x_mean = (period - 1) / 2.0; x_var = 0.0 + for j in range(period): x_var += (j - x_mean) ** 2 + for i in range(period - 1, n): + y_mean = 0.0 + for j in range(period): y_mean += close[i - period + 1 + j] + y_mean /= period + slope = 0.0 + for j in range(period): slope += (j - x_mean) * (close[i - period + 1 + j] - y_mean) + slope /= x_var + out[i] = y_mean + slope * (period - 1 - x_mean) + return out + +@nb.njit(cache=True) +def ma_swma(close, period, p1): + n = len(close); out = np.full(n, np.nan) + if n < period: return out + w = np.empty(period); ws = 0.0 + for j in range(period): + wj = min(j + 1, period - j); w[j] = wj; ws += wj + for i in range(period - 1, n): + s = 0.0 + for j in range(period): s += close[i - period + 1 + j] * w[j] + out[i] = s / ws + return out + +# ═══════════════════════════════════════════════════════════════════════════ +# CHANNELS / LEVELS (IDs 17-28) +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def bb_upper(close, period, p1): + mult = p1 if p1 > 0 else 2.0 + sma_v = _sma(close, period); n = len(close); out = np.full(n, np.nan) + for i in range(period - 1, n): + s = 0.0 + for j in range(i - period + 1, i + 1): s += (close[j] - sma_v[i]) ** 2 + out[i] = sma_v[i] + mult * math.sqrt(s / (period - 1)) + return out + +@nb.njit(cache=True) +def bb_lower(close, period, p1): + mult = p1 if p1 > 0 else 2.0 + sma_v = _sma(close, period); n = len(close); out = np.full(n, np.nan) + for i in range(period - 1, n): + s = 0.0 + for j in range(i - period + 1, i + 1): s += (close[j] - sma_v[i]) ** 2 + out[i] = sma_v[i] - mult * math.sqrt(s / (period - 1)) + return out + +@nb.njit(cache=True) +def supertrend(close, high, low, period, p1): + mult = p1 if p1 > 0 else 3.0 + tr = _true_range(high, low, close); atr = _rma(tr, period) + n = len(close); st = np.full(n, np.nan) + upper = np.full(n, np.nan); lower = np.full(n, np.nan); direction = np.ones(n) + for i in range(period, n): + if np.isnan(atr[i]): continue + hl2 = (high[i] + low[i]) / 2.0 + bu = hl2 + mult * atr[i]; bl = hl2 - mult * atr[i] + if i == period: + upper[i] = bu; lower[i] = bl + st[i] = lower[i] if close[i] > lower[i] else upper[i] + direction[i] = 1.0 if close[i] > st[i] else -1.0; continue + upper[i] = min(bu, upper[i-1]) if not np.isnan(upper[i-1]) and close[i-1] <= upper[i-1] else bu + lower[i] = max(bl, lower[i-1]) if not np.isnan(lower[i-1]) and close[i-1] >= lower[i-1] else bl + if direction[i-1] == 1.0: + st[i] = lower[i] if close[i] >= lower[i] else upper[i] + else: + st[i] = upper[i] if close[i] <= upper[i] else lower[i] + direction[i] = 1.0 if close[i] > st[i] else -1.0 + return st + +@nb.njit(cache=True) +def donch_upper(high, period, p1): + n = len(high); out = np.full(n, np.nan) + for i in range(period - 1, n): + mx = -1e18 + for j in range(i - period + 1, i + 1): + if high[j] > mx: mx = high[j] + out[i] = mx + return out + +@nb.njit(cache=True) +def donch_lower(low, period, p1): + n = len(low); out = np.full(n, np.nan) + for i in range(period - 1, n): + mn = 1e18 + for j in range(i - period + 1, i + 1): + if low[j] < mn: mn = low[j] + out[i] = mn + return out + +@nb.njit(cache=True) +def kelt_upper(close, high, low, period, p1): + mult = p1 if p1 > 0 else 1.5 + basis = _ema(close, period); atr = _atr(close, high, low, period) + n = len(close); out = np.full(n, np.nan) + for i in range(n): + if not np.isnan(basis[i]) and not np.isnan(atr[i]): + out[i] = basis[i] + mult * atr[i] + return out + +@nb.njit(cache=True) +def kelt_lower(close, high, low, period, p1): + mult = p1 if p1 > 0 else 1.5 + basis = _ema(close, period); atr = _atr(close, high, low, period) + n = len(close); out = np.full(n, np.nan) + for i in range(n): + if not np.isnan(basis[i]) and not np.isnan(atr[i]): + out[i] = basis[i] - mult * atr[i] + return out + +@nb.njit(cache=True) +def ichimoku_midline(high, low, period): + n = len(high); out = np.full(n, np.nan) + for i in range(period-1, n): + hh = -1e18; ll = 1e18 + for j in range(i-period+1, i+1): + if high[j] > hh: hh = high[j] + if low[j] < ll: ll = low[j] + out[i] = (hh+ll)/2.0 + return out + +@nb.njit(cache=True) +def psar(close, high, low, period, p1): + af_step = p1 if p1 > 0 else 0.02 + n = len(close); out = np.full(n, np.nan) + if n < 2: return out + bull = True; af = 0.02; af_max = 0.2; ep = high[0]; sar = low[0] + for i in range(1, n): + prev_sar = sar; sar = prev_sar + af * (ep - prev_sar) + if bull: + sar = min(sar, low[i-1]) + if i >= 2: sar = min(sar, low[i-2]) + if low[i] < sar: + bull = False; sar = ep; ep = low[i]; af = 0.02 + else: + if high[i] > ep: ep = high[i]; af = min(af + af_step, af_max) + else: + sar = max(sar, high[i-1]) + if i >= 2: sar = max(sar, high[i-2]) + if high[i] > sar: + bull = True; sar = ep; ep = high[i]; af = 0.02 + else: + if low[i] < ep: ep = low[i]; af = min(af + af_step, af_max) + out[i] = sar + return out + +# ═══════════════════════════════════════════════════════════════════════════ +# OSCILLATORS (IDs 30-44) +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def osc_rsi(close, period, p1): + n = len(close); out = np.full(n, np.nan) + if n < period + 1: return out + ag = 0.0; al = 0.0 + for i in range(1, period + 1): + d = close[i] - close[i - 1] + if d > 0: ag += d + else: al -= d + ag /= period; al /= period + out[period] = 100.0 - 100.0 / (1.0 + ag / al) if al > 0 else 100.0 + alpha = 1.0 / period + for i in range(period + 1, n): + d = close[i] - close[i - 1] + g = d if d > 0 else 0.0; l = -d if d < 0 else 0.0 + ag = alpha * g + (1 - alpha) * ag + al = alpha * l + (1 - alpha) * al + out[i] = 100.0 - 100.0 / (1.0 + ag / al) if al > 0 else 100.0 + return out + +@nb.njit(cache=True) +def osc_stoch_k(close, high, low, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period - 1, n): + hh = -1e18; ll = 1e18 + for j in range(i - period + 1, i + 1): + if high[j] > hh: hh = high[j] + if low[j] < ll: ll = low[j] + out[i] = 100.0 * (close[i] - ll) / (hh - ll) if (hh - ll) > 0 else 50.0 + return out + +@nb.njit(cache=True) +def osc_stoch_d(close, high, low, period, p1): + k = osc_stoch_k(close, high, low, period, p1) + return _sma(k, 3) + +@nb.njit(cache=True) +def osc_cci(close, high, low, period, p1): + n = len(close); tp = (close + high + low) / 3.0; tp_sma = _sma(tp, period) + out = np.full(n, np.nan) + for i in range(period - 1, n): + if np.isnan(tp_sma[i]): continue + md = 0.0 + for j in range(i - period + 1, i + 1): md += abs(tp[j] - tp_sma[i]) + md /= period + out[i] = (tp[i] - tp_sma[i]) / (0.015 * md) if md > 0 else 0.0 + return out + +@nb.njit(cache=True) +def osc_williams_r(close, high, low, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period - 1, n): + hh = -1e18; ll = 1e18 + for j in range(i - period + 1, i + 1): + if high[j] > hh: hh = high[j] + if low[j] < ll: ll = low[j] + out[i] = -100.0 * (hh - close[i]) / (hh - ll) if (hh - ll) > 0 else -50.0 + return out + +@nb.njit(cache=True) +def osc_roc(close, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + if close[i - period] != 0: out[i] = 100.0 * (close[i] - close[i - period]) / close[i - period] + return out + +@nb.njit(cache=True) +def osc_cmo(close, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + ups = 0.0; dns = 0.0 + for j in range(i - period + 1, i + 1): + d = close[j] - close[j - 1] + if d > 0: ups += d + else: dns -= d + s = ups + dns + out[i] = 100.0 * (ups - dns) / s if s > 0 else 0.0 + return out + +@nb.njit(cache=True) +def osc_trix(close, period, p1): + n = len(close); e1 = _ema(close, period); fv = close[0] + t = np.empty(n) + for i in range(n): t[i] = e1[i] if not np.isnan(e1[i]) else fv + e2 = _ema(t, period) + for i in range(n): t[i] = e2[i] if not np.isnan(e2[i]) else fv + e3 = _ema(t, period) + out = np.full(n, np.nan) + for i in range(1, n): + if not np.isnan(e3[i]) and not np.isnan(e3[i - 1]) and e3[i - 1] != 0: + out[i] = 10000.0 * (e3[i] - e3[i - 1]) / e3[i - 1] + return out + +@nb.njit(cache=True) +def osc_ppo(close, period, p1): + fast = max(period // 2, 2); ef = _ema(close, fast); es = _ema(close, period) + n = len(close); out = np.full(n, np.nan) + for i in range(n): + if not np.isnan(ef[i]) and not np.isnan(es[i]) and es[i] != 0: + out[i] = 100.0 * (ef[i] - es[i]) / es[i] + return out + +@nb.njit(cache=True) +def osc_macd_hist(close, period, p1): + fast = max(period // 2, 2); signal_p = 9 + ef = _ema(close, fast); es = _ema(close, period); n = len(close) + macd = np.full(n, np.nan) + for i in range(n): + if not np.isnan(ef[i]) and not np.isnan(es[i]): macd[i] = ef[i] - es[i] + t = np.empty(n); fv = 0.0 + for i in range(n): + if not np.isnan(macd[i]): fv = macd[i]; break + for i in range(n): t[i] = macd[i] if not np.isnan(macd[i]) else fv + sig = _ema(t, signal_p); out = np.full(n, np.nan) + warmup = period + signal_p + for i in range(warmup, n): + if not np.isnan(macd[i]) and not np.isnan(sig[i]): out[i] = macd[i] - sig[i] + return out + +@nb.njit(cache=True) +def osc_mfi(close, high, low, volume, period, p1): + tp = (close + high + low) / 3.0; mf = tp * volume + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + pos = 0.0; neg = 0.0 + for j in range(i - period + 1, i + 1): + if tp[j] > tp[j - 1]: pos += mf[j] + elif tp[j] < tp[j - 1]: neg += mf[j] + out[i] = 100.0 - 100.0 / (1.0 + pos / neg) if neg > 0 else 100.0 + return out + +@nb.njit(cache=True) +def osc_dpo(close, period, p1): + shift = period // 2 + 1; sma_v = _sma(close, period) + n = len(close); out = np.full(n, np.nan) + for i in range(shift, n): + if not np.isnan(sma_v[i]): out[i] = close[i - shift] - sma_v[i] + return out + +@nb.njit(cache=True) +def norm_pctile_rank(close, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + cnt = 0 + for j in range(i - period + 1, i + 1): + if close[j] <= close[i]: cnt += 1 + out[i] = 100.0 * cnt / period + return out + +@nb.njit(cache=True) +def norm_zscore(close, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + m = 0.0 + for j in range(i - period + 1, i + 1): m += close[j] + m /= period; s = 0.0 + for j in range(i - period + 1, i + 1): s += (close[j] - m) ** 2 + std = math.sqrt(s / (period - 1)) if period > 1 else 1e-10 + out[i] = (close[i] - m) / std if std > 0 else 0.0 + return out + +@nb.njit(cache=True) +def norm_minmax(close, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + mn = 1e18; mx = -1e18 + for j in range(i - period + 1, i + 1): + if close[j] < mn: mn = close[j] + if close[j] > mx: mx = close[j] + out[i] = (close[i] - mn) / (mx - mn) if (mx - mn) > 0 else 0.5 + return out + +# ═══════════════════════════════════════════════════════════════════════════ +# VOLATILITY / FILTER (IDs 50-63) +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def vol_atr(close, high, low, period, p1): + return _atr(close, high, low, period) + +@nb.njit(cache=True) +def vol_atr_pct(close, high, low, period, p1): + atr = _atr(close, high, low, period) + n = len(close); out = np.full(n, np.nan) + for i in range(n): + if not np.isnan(atr[i]) and close[i] > 0: out[i] = 100.0 * atr[i] / close[i] + return out + +@nb.njit(cache=True) +def vol_atr_zscore(close, high, low, period, p1): + n = len(close); tr = _true_range(high, low, close); out = np.full(n, np.nan) + for i in range(period, n): + m = 0.0; s = 0.0 + for j in range(i - period + 1, i + 1): m += tr[j] + m /= period + for j in range(i - period + 1, i + 1): s += (tr[j] - m) ** 2 + std = math.sqrt(s / (period - 1)) if period > 1 else 1e-10 + out[i] = (tr[i] - m) / std if std > 0 else 0.0 + return out + +@nb.njit(cache=True) +def vol_compression(close, high, low, period, p1): + n = len(close); tr = _true_range(high, low, close); out = np.full(n, np.nan) + for i in range(period, n): + atr_sum = 0.0; c_mean = 0.0; c_ss = 0.0 + for j in range(i - period + 1, i + 1): atr_sum += tr[j]; c_mean += close[j] + atr_sum /= period; c_mean /= period + for j in range(i - period + 1, i + 1): c_ss += (close[j] - c_mean) ** 2 + std = math.sqrt(c_ss / (period - 1)) if period > 1 else 1e-10 + out[i] = std / atr_sum if atr_sum > 0 else 1.0 + return out + +@nb.njit(cache=True) +def vol_of_vol(close, high, low, period, p1): + n = len(close); tr = _true_range(high, low, close) + atr = np.full(n, np.nan); s = 0.0 + for j in range(period): s += tr[j] + atr[period - 1] = s / period; alpha = 1.0 / period + for i in range(period, n): atr[i] = alpha * tr[i] + (1 - alpha) * atr[i - 1] + out = np.full(n, np.nan) + for i in range(2 * period, n): + m = 0.0 + for j in range(i - period + 1, i + 1): m += atr[j] + m /= period; s = 0.0 + for j in range(i - period + 1, i + 1): s += (atr[j] - m) ** 2 + out[i] = math.sqrt(s / (period - 1)) if period > 1 else 0.0 + return out + +@nb.njit(cache=True) +def vol_parkinson(close, high, low, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + s = 0.0 + for j in range(i - period + 1, i + 1): + if low[j] > 0: s += (math.log(high[j] / low[j])) ** 2 + out[i] = math.sqrt(s / (4.0 * period * math.log(2.0))) + return out + +@nb.njit(cache=True) +def vol_garman_klass(close, high, low, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period + 1, n): + s = 0.0 + for j in range(i - period + 1, i + 1): + if low[j] > 0 and close[j - 1] > 0: + hl = math.log(high[j] / low[j]); co = math.log(close[j] / close[j - 1]) + s += 0.5 * hl * hl - (2 * math.log(2.0) - 1) * co * co + out[i] = math.sqrt(max(s / period, 0.0)) + return out + +@nb.njit(cache=True) +def vol_rogers_satchell(close, high, low, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period + 1, n): + s = 0.0 + for j in range(i - period + 1, i + 1): + o = close[j - 1] + if o > 0 and low[j] > 0: + s += math.log(high[j]/o)*math.log(high[j]/close[j]) + math.log(low[j]/o)*math.log(low[j]/close[j]) + out[i] = math.sqrt(max(s / period, 0.0)) + return out + +@nb.njit(cache=True) +def vol_realized(close, high, low, period, p1): + n = len(close); out = np.full(n, np.nan); ann = math.sqrt(252.0 * 720.0) + for i in range(period + 1, n): + m = 0.0 + for j in range(period): + if close[i - period + j] > 0: m += math.log(close[i - period + j + 1] / close[i - period + j]) + m /= period; s = 0.0 + for j in range(period): + if close[i - period + j] > 0: + lr = math.log(close[i - period + j + 1] / close[i - period + j]); s += (lr - m) ** 2 + out[i] = math.sqrt(s / (period - 1)) * ann if period > 1 else 0.0 + return out + +@nb.njit(cache=True) +def vol_range_pctile(close, high, low, period, p1): + n = len(close); out = np.full(n, np.nan) + lb = max(int(p1), period * 5) if p1 > 0 else period * 5 + for i in range(lb, n): + curr = high[i] - low[i]; cnt = 0 + for j in range(i - lb + 1, i + 1): + if (high[j] - low[j]) <= curr: cnt += 1 + out[i] = 100.0 * cnt / lb + return out + +@nb.njit(cache=True) +def vol_tr_momentum(close, high, low, period, p1): + n = len(close); tr = _true_range(high, low, close) + atr = np.full(n, np.nan) + for i in range(period - 1, n): + s = 0.0 + for j in range(i - period + 1, i + 1): s += tr[j] + atr[i] = s / period + out = np.full(n, np.nan); lag = max(period // 2, 1) + for i in range(period + lag, n): + if not np.isnan(atr[i]) and not np.isnan(atr[i - lag]) and atr[i - lag] > 0: + out[i] = (atr[i] - atr[i - lag]) / atr[i - lag] + return out + +@nb.njit(cache=True) +def norm_vol_zscore(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + m = 0.0 + for j in range(i - period + 1, i + 1): m += volume[j] + m /= period; s = 0.0 + for j in range(i - period + 1, i + 1): s += (volume[j] - m) ** 2 + std = math.sqrt(s / (period - 1)) if period > 1 else 1e-10 + out[i] = (volume[i] - m) / std if std > 0 else 0.0 + return out + +@nb.njit(cache=True) +def micro_vol_clustering(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + m = 0.0 + for j in range(i - period + 1, i + 1): m += volume[j] + m /= period; s = 0.0 + for j in range(i - period + 1, i + 1): s += (volume[j] - m) ** 2 + std = math.sqrt(s / (period - 1)) if period > 1 else 0.0 + out[i] = std / m if m > 0 else 0.0 + return out + +@nb.njit(cache=True) +def micro_vol_delta(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + delta = 0.0 + for j in range(i - period + 1, i + 1): + rng = high[j] - low[j] + bp = (close[j] - low[j]) / rng if rng > 0 else 0.5 + delta += volume[j] * (2 * bp - 1) + out[i] = delta + return out + +# ═══════════════════════════════════════════════════════════════════════════ +# TREND / REGIME (IDs 70-83, 168) +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def adx(close, high, low, period, p1): + n = len(close); out = np.full(n, np.nan) + if n < period * 2: return out + tr = _true_range(high, low, close) + pdm = np.zeros(n); mdm = np.zeros(n) + for i in range(1, n): + up = high[i] - high[i-1]; dn = low[i-1] - low[i] + pdm[i] = up if (up > dn and up > 0) else 0.0 + mdm[i] = dn if (dn > up and dn > 0) else 0.0 + a = 1.0 / period + atr_v = np.full(n, np.nan); p_v = np.full(n, np.nan); m_v = np.full(n, np.nan) + s1 = 0.0; s2 = 0.0; s3 = 0.0 + for j in range(period): s1 += tr[j]; s2 += pdm[j]; s3 += mdm[j] + atr_v[period-1] = s1/period; p_v[period-1] = s2/period; m_v[period-1] = s3/period + for i in range(period, n): + atr_v[i] = a*tr[i]+(1-a)*atr_v[i-1]; p_v[i] = a*pdm[i]+(1-a)*p_v[i-1]; m_v[i] = a*mdm[i]+(1-a)*m_v[i-1] + dx = np.full(n, np.nan) + for i in range(period, n): + if atr_v[i] > 0: + pdi = 100.0*p_v[i]/atr_v[i]; mdi = 100.0*m_v[i]/atr_v[i]; s = pdi + mdi + if s > 0: dx[i] = 100.0 * abs(pdi - mdi) / s + s = 0.0; cnt = 0; start = -1 + for i in range(period, n): + if not np.isnan(dx[i]): + s += dx[i]; cnt += 1 + if cnt == period: start = i; break + if start >= 0: + out[start] = s / period + for i in range(start + 1, n): + if not np.isnan(dx[i]): out[i] = a*dx[i]+(1-a)*out[i-1] + else: out[i] = out[i-1] + return out + +@nb.njit(cache=True) +def aroon_up(high, period, p1): + n = len(high); out = np.full(n, np.nan) + for i in range(period, n): + mx = -1e18; idx = 0 + for j in range(period + 1): + if high[i - period + j] > mx: mx = high[i - period + j]; idx = j + out[i] = 100.0 * idx / period + return out + +@nb.njit(cache=True) +def aroon_down(low, period, p1): + n = len(low); out = np.full(n, np.nan) + for i in range(period, n): + mn = 1e18; idx = 0 + for j in range(period + 1): + if low[i - period + j] < mn: mn = low[i - period + j]; idx = j + out[i] = 100.0 * idx / period + return out + +@nb.njit(cache=True) +def linreg_slope(close, period, p1): + n = len(close); out = np.full(n, np.nan) + x_mean = (period - 1) / 2.0; x_var = 0.0 + for j in range(period): x_var += (j - x_mean) ** 2 + for i in range(period - 1, n): + y_mean = 0.0 + for j in range(period): y_mean += close[i - period + 1 + j] + y_mean /= period; slope = 0.0 + for j in range(period): slope += (j - x_mean) * (close[i - period + 1 + j] - y_mean) + slope /= x_var if x_var > 0 else 1.0 + out[i] = slope / y_mean * 10000 if y_mean > 0 else 0.0 + return out + +@nb.njit(cache=True) +def linreg_r2(close, period, p1): + n = len(close); out = np.full(n, np.nan) + x_mean = (period - 1) / 2.0; x_var = 0.0 + for j in range(period): x_var += (j - x_mean) ** 2 + for i in range(period - 1, n): + y_mean = 0.0 + for j in range(period): y_mean += close[i - period + 1 + j] + y_mean /= period; slope = 0.0 + for j in range(period): slope += (j - x_mean) * (close[i - period + 1 + j] - y_mean) + slope /= x_var if x_var > 0 else 1.0 + intercept = y_mean - slope * x_mean; ss_res = 0.0; ss_tot = 0.0 + for j in range(period): + yj = close[i - period + 1 + j]; pred = slope * j + intercept + ss_res += (yj - pred) ** 2; ss_tot += (yj - y_mean) ** 2 + out[i] = 1.0 - ss_res / ss_tot if ss_tot > 0 else 0.0 + return out + +@nb.njit(cache=True) +def trend_efficiency(close, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + net = abs(close[i] - close[i - period]); path = 0.0 + for j in range(i - period + 1, i + 1): path += abs(close[j] - close[j - 1]) + out[i] = net / path if path > 0 else 0.0 + return out + +@nb.njit(cache=True) +def trend_angle(close, period, p1): + slope = linreg_slope(close, period, p1) + n = len(close); out = np.full(n, np.nan) + for i in range(n): + if not np.isnan(slope[i]): out[i] = math.degrees(math.atan(slope[i] / 100.0)) + return out + +@nb.njit(cache=True) +def trend_duration(close, period, p1): + n = len(close); out = np.full(n, np.nan); streak = 0.0 + for i in range(1, n): + if close[i] > close[i-1]: streak = streak + 1 if streak > 0 else 1 + elif close[i] < close[i-1]: streak = streak - 1 if streak < 0 else -1 + else: streak = 0 + out[i] = streak + return out + +@nb.njit(cache=True) +def regime_hurst(close, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + mean = 0.0 + for j in range(i - period + 1, i + 1): mean += close[j] + mean /= period; cum = 0.0; mn = 1e18; mx = -1e18; ss = 0.0 + for j in range(i - period + 1, i + 1): + cum += close[j] - mean + if cum < mn: mn = cum + if cum > mx: mx = cum + d = close[j] - mean; ss += d * d + R = mx - mn; S = math.sqrt(ss / period) + if S > 0 and R > 0 and period > 1: out[i] = math.log(R / S) / math.log(period) + else: out[i] = 0.5 + return out + +@nb.njit(cache=True) +def regime_variance_ratio(close, period, p1): + n = len(close); out = np.full(n, np.nan) + q = max(int(p1), 2) if p1 > 1 else 2 + for i in range(period + q, n): + rets = np.empty(period) + for j in range(period): + idx = i - period + j + rets[j] = math.log(close[idx+1] / close[idx]) if close[idx] > 0 else 0.0 + var1 = 0.0; m1 = 0.0 + for j in range(period): m1 += rets[j] + m1 /= period + for j in range(period): var1 += (rets[j] - m1) ** 2 + var1 /= (period - 1) if period > 1 else 1 + nq = period - q + 1 + if nq < 2: continue + mq = 0.0; q_rets = np.empty(nq) + for j in range(nq): + s = 0.0 + for k in range(q): s += rets[j + k] + q_rets[j] = s; mq += s + mq /= nq; varq = 0.0 + for j in range(nq): varq += (q_rets[j] - mq) ** 2 + varq /= (nq - 1) if nq > 1 else 1 + out[i] = varq / (q * var1) if var1 > 0 else 1.0 + return out + +@nb.njit(cache=True) +def regime_fractal_dim(close, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + mx = -1e18; mn = 1e18; length = 0.0 + for j in range(i - period + 1, i + 1): + if close[j] > mx: mx = close[j] + if close[j] < mn: mn = close[j] + for j in range(i - period + 2, i + 1): length += abs(close[j] - close[j - 1]) + if (mx - mn) > 0 and length > 0: + out[i] = 1.0 + (math.log(length) + math.log(2.0)) / (math.log(2.0 * period) + math.log(mx - mn)) + else: out[i] = 1.5 + return out + +@nb.njit(cache=True) +def regime_trend_persist(close, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period + 1, n): + runs = 0 + for j in range(i - period + 2, i + 1): + d1 = close[j] - close[j - 1]; d2 = close[j - 1] - close[j - 2] + if (d1 > 0 and d2 > 0) or (d1 < 0 and d2 < 0): runs += 1 + out[i] = runs / (period - 1) if period > 1 else 0.5 + return out + +@nb.njit(cache=True) +def regime_autocorr(close, period, p1): + lag = max(int(p1), 1) if p1 > 0 else 1 + n = len(close); out = np.full(n, np.nan) + for i in range(period + 1, n): + rets = np.empty(period) + for j in range(period): rets[j] = close[i - period + j + 1] - close[i - period + j] + if period <= lag: continue + x = rets[:period - lag]; y = rets[lag:]; nn = period - lag + mx = 0.0; my = 0.0 + for j in range(nn): mx += x[j]; my += y[j] + mx /= nn; my /= nn + cov = 0.0; sx = 0.0; sy = 0.0 + for j in range(nn): + dx = x[j] - mx; dy = y[j] - my; cov += dx * dy; sx += dx * dx; sy += dy * dy + sx = math.sqrt(sx / (nn - 1)) if nn > 1 else 1e-10 + sy = math.sqrt(sy / (nn - 1)) if nn > 1 else 1e-10 + out[i] = (cov / nn) / (sx * sy) if sx > 0 and sy > 0 else 0.0 + return out + +@nb.njit(cache=True) +def micro_trend_struct(close, high, low, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + score = 0 + for j in range(i - period + 2, i + 1): + if high[j] > high[j - 1]: score += 1 + else: score -= 1 + if low[j] > low[j - 1]: score += 1 + else: score -= 1 + out[i] = score / (2.0 * (period - 1)) if period > 1 else 0.0 + return out + +@nb.njit(cache=True) +def trend_lhll_score(close, high, low, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + lh = 0; ll = 0 + for j in range(i - period + 2, i + 1): + if high[j] < high[j - 1]: lh += 1 + if low[j] < low[j - 1]: ll += 1 + out[i] = -(lh + ll) / (2.0 * (period - 1)) if period > 1 else 0.0 + return out + +# ═══════════════════════════════════════════════════════════════════════════ +# DEPTH: PIVOT / REFERENCE LEVELS (IDs 120-131) +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def pivot_classic(close, high, low, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + hh = -1e18; ll = 1e18 + for j in range(i - period + 1, i + 1): + if high[j] > hh: hh = high[j] + if low[j] < ll: ll = low[j] + out[i] = (hh + ll + close[i]) / 3.0 + return out + +@nb.njit(cache=True) +def pivot_r1(close, high, low, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + hh = -1e18; ll = 1e18 + for j in range(i - period + 1, i + 1): + if high[j] > hh: hh = high[j] + if low[j] < ll: ll = low[j] + pivot = (hh + ll + close[i]) / 3.0; out[i] = 2.0 * pivot - ll + return out + +@nb.njit(cache=True) +def pivot_s1(close, high, low, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + hh = -1e18; ll = 1e18 + for j in range(i - period + 1, i + 1): + if high[j] > hh: hh = high[j] + if low[j] < ll: ll = low[j] + pivot = (hh + ll + close[i]) / 3.0; out[i] = 2.0 * pivot - hh + return out + +@nb.njit(cache=True) +def prev_period_high(close, high, low, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(2 * period, n): + hh = -1e18 + for j in range(i - 2 * period + 1, i - period + 1): + if high[j] > hh: hh = high[j] + out[i] = hh + return out + +@nb.njit(cache=True) +def prev_period_low(close, high, low, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(2 * period, n): + ll = 1e18 + for j in range(i - 2 * period + 1, i - period + 1): + if low[j] < ll: ll = low[j] + out[i] = ll + return out + +@nb.njit(cache=True) +def prev_period_close(close, high, low, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): out[i] = close[i - period] + return out + +@nb.njit(cache=True) +def rolling_median(close, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period - 1, n): + window = close[i - period + 1:i + 1].copy(); window.sort() + mid = period // 2 + out[i] = window[mid] if period % 2 == 1 else (window[mid - 1] + window[mid]) / 2.0 + return out + +@nb.njit(cache=True) +def linreg_channel_upper(close, period, p1): + mult = p1 if p1 > 0 else 2.0; n = len(close); out = np.full(n, np.nan) + x_mean = (period - 1) / 2.0; x_var = 0.0 + for j in range(period): x_var += (j - x_mean) ** 2 + for i in range(period - 1, n): + y_mean = 0.0 + for j in range(period): y_mean += close[i - period + 1 + j] + y_mean /= period; slope = 0.0 + for j in range(period): slope += (j - x_mean) * (close[i - period + 1 + j] - y_mean) + slope /= x_var if x_var > 0 else 1.0 + intercept = y_mean - slope * x_mean; ss = 0.0 + for j in range(period): + pred = slope * j + intercept; ss += (close[i - period + 1 + j] - pred) ** 2 + std = math.sqrt(ss / (period - 1)) if period > 1 else 0.0 + reg_val = slope * (period - 1) + intercept + out[i] = reg_val + mult * std + return out + +@nb.njit(cache=True) +def linreg_channel_lower(close, period, p1): + mult = p1 if p1 > 0 else 2.0; n = len(close); out = np.full(n, np.nan) + x_mean = (period - 1) / 2.0; x_var = 0.0 + for j in range(period): x_var += (j - x_mean) ** 2 + for i in range(period - 1, n): + y_mean = 0.0 + for j in range(period): y_mean += close[i - period + 1 + j] + y_mean /= period; slope = 0.0 + for j in range(period): slope += (j - x_mean) * (close[i - period + 1 + j] - y_mean) + slope /= x_var if x_var > 0 else 1.0 + intercept = y_mean - slope * x_mean; ss = 0.0 + for j in range(period): + pred = slope * j + intercept; ss += (close[i - period + 1 + j] - pred) ** 2 + std = math.sqrt(ss / (period - 1)) if period > 1 else 0.0 + reg_val = slope * (period - 1) + intercept + out[i] = reg_val - mult * std + return out + +@nb.njit(cache=True) +def quantile_band_upper(close, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period - 1, n): + window = close[i - period + 1:i + 1].copy(); window.sort() + out[i] = window[int(0.9 * (period - 1))] + return out + +@nb.njit(cache=True) +def quantile_band_lower(close, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period - 1, n): + window = close[i - period + 1:i + 1].copy(); window.sort() + out[i] = window[int(0.1 * (period - 1))] + return out + +# ═══════════════════════════════════════════════════════════════════════════ +# FILTER extras (IDs 111-119) +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def entropy_shannon(close, period, p1): + n = len(close); out = np.full(n, np.nan); bins = 10 + for i in range(period + 1, n): + rets = np.empty(period) + for j in range(period): rets[j] = close[i - period + j + 1] - close[i - period + j] + mn = rets[0]; mx = rets[0] + for j in range(period): + if rets[j] < mn: mn = rets[j] + if rets[j] > mx: mx = rets[j] + rng = mx - mn + if rng == 0: rng = 1.0 + hist = np.zeros(bins) + for j in range(period): + b = int((rets[j] - mn) / rng * (bins - 1)) + if b >= bins: b = bins - 1 + if b < 0: b = 0 + hist[b] += 1 + entropy = 0.0 + for b in range(bins): + if hist[b] > 0: + prob = hist[b] / period; entropy -= prob * math.log2(prob) + out[i] = entropy + return out + +@nb.njit(cache=True) +def regime_kurtosis(close, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period + 1, n): + m = 0.0 + for j in range(period): m += close[i - period + j + 1] - close[i - period + j] + m /= period; s2 = 0.0; s4 = 0.0 + for j in range(period): + d = (close[i - period + j + 1] - close[i - period + j]) - m; s2 += d*d; s4 += d*d*d*d + s2 /= (period - 1) if period > 1 else 1 + std = math.sqrt(s2) if s2 > 0 else 1e-10 + out[i] = (s4 / period) / (std ** 4) - 3.0 if std > 0 else 0.0 + return out + +@nb.njit(cache=True) +def regime_halflife(close, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period + 1, n): + m = 0.0 + for j in range(i - period, i + 1): m += close[j] + m /= (period + 1); sxy = 0.0; sxx = 0.0 + for j in range(i - period, i): + x = close[j] - m; y = close[j + 1] - close[j]; sxy += x * y; sxx += x * x + if sxx == 0: continue + beta = sxy / sxx + out[i] = -math.log(2.0) / beta if beta < 0 else float(period) + return out + +@nb.njit(cache=True) +def regime_dc_events(close, period, p1): + threshold = p1 / 10000.0 if p1 > 0 else 0.001 + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + changes = 0; direction = 0; extreme = close[i - period + 1] + for j in range(i - period + 2, i + 1): + if direction >= 0 and extreme > 0 and (extreme - close[j]) / extreme >= threshold: + changes += 1; direction = -1; extreme = close[j] + elif direction <= 0 and extreme > 0 and (close[j] - extreme) / extreme >= threshold: + changes += 1; direction = 1; extreme = close[j] + else: + if direction == 1 and close[j] > extreme: extreme = close[j] + elif direction == -1 and close[j] < extreme: extreme = close[j] + out[i] = float(changes) + return out + +@nb.njit(cache=True) +def cross_ma_compression(close, period, p1): + n = len(close) + ps = [max(period//4,2), max(period//2,3), period, min(period*2, 50)] + emas = np.empty((4, n)) + for k in range(4): + pp = ps[k]; alpha = 2.0/(pp+1); s = 0.0 + for j in range(pp): s += close[j] + emas[k, pp-1] = s/pp + for j in range(pp-1): emas[k,j] = np.nan + for i in range(pp, n): emas[k,i] = alpha*close[i]+(1-alpha)*emas[k,i-1] + out = np.full(n, np.nan); mx_p = min(period*2, 50) + for i in range(mx_p, n): + vals = np.empty(4); cnt = 0 + for k in range(4): + if not np.isnan(emas[k,i]): vals[cnt] = emas[k,i]; cnt += 1 + if cnt >= 3 and close[i] > 0: + m = 0.0 + for j in range(cnt): m += vals[j] + m /= cnt; s = 0.0 + for j in range(cnt): s += (vals[j]-m)**2 + out[i] = math.sqrt(s/cnt)/close[i]*10000 + return out + +@nb.njit(cache=True) +def time_hour_sin(period, n): + out = np.empty(n) + for i in range(n): out[i] = math.sin(2*math.pi*(i % 720)/720.0) + return out + +@nb.njit(cache=True) +def time_hour_cos(period, n): + out = np.empty(n) + for i in range(n): out[i] = math.cos(2*math.pi*(i % 720)/720.0) + return out + +@nb.njit(cache=True) +def time_session_vol(close, period, p1): + n = len(close); out = np.full(n, np.nan); sl = 360 + for i in range(sl + 1, n): + m = 0.0 + for j in range(sl): m += close[i - sl + j + 1] - close[i - sl + j] + m /= sl; s = 0.0 + for j in range(sl): + d = (close[i - sl + j + 1] - close[i - sl + j]) - m; s += d * d + out[i] = math.sqrt(s / (sl - 1)) + return out + +@nb.njit(cache=True) +def regime_skewness(close, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period + 1, n): + m = 0.0 + for j in range(period): m += close[i-period+j+1] - close[i-period+j] + m /= period; s2 = 0.0; s3 = 0.0 + for j in range(period): + d = (close[i-period+j+1] - close[i-period+j]) - m; s2 += d*d; s3 += d*d*d + s2 /= (period-1) if period > 1 else 1 + std = math.sqrt(s2) if s2 > 0 else 1e-10 + out[i] = (s3/period) / (std**3) if std > 0 else 0.0 + return out + +@nb.njit(cache=True) +def norm_return_zscore(close, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period + 1, n): + curr = close[i] - close[i-1]; m = 0.0 + for j in range(period): m += close[i-period+j+1] - close[i-period+j] + m /= period; s = 0.0 + for j in range(period): + d = (close[i-period+j+1] - close[i-period+j]) - m; s += d*d + std = math.sqrt(s/(period-1)) if period > 1 else 1e-10 + out[i] = (curr-m)/std if std > 0 else 0.0 + return out + +# ═══════════════════════════════════════════════════════════════════════════ +# MICROSTRUCTURE (IDs 90-97) +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def micro_body_ratio(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + s = 0.0 + for j in range(i-period+1, i+1): + rng = high[j]-low[j]; o = close[j-1] if j > 0 else close[j] + s += abs(close[j]-o)/rng if rng > 0 else 0.5 + out[i] = s/period + return out + +@nb.njit(cache=True) +def micro_upper_wick(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + s = 0.0 + for j in range(i-period+1, i+1): + rng = high[j]-low[j]; o = close[j-1] if j > 0 else close[j] + s += (high[j]-max(close[j],o))/rng if rng > 0 else 0.0 + out[i] = s/period + return out + +@nb.njit(cache=True) +def micro_lower_wick(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + s = 0.0 + for j in range(i-period+1, i+1): + rng = high[j]-low[j]; o = close[j-1] if j > 0 else close[j] + s += (min(close[j],o)-low[j])/rng if rng > 0 else 0.0 + out[i] = s/period + return out + +@nb.njit(cache=True) +def micro_buy_pressure(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + s = 0.0 + for j in range(i-period+1, i+1): + rng = high[j]-low[j] + s += (close[j]-low[j])/rng if rng > 0 else 0.5 + out[i] = s/period + return out + +@nb.njit(cache=True) +def micro_sell_pressure(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + s = 0.0 + for j in range(i-period+1, i+1): + rng = high[j]-low[j] + s += (high[j]-close[j])/rng if rng > 0 else 0.5 + out[i] = s/period + return out + +@nb.njit(cache=True) +def micro_stop_hunt(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + o = close[i-1] if i > 0 else close[i] + upper_wick = high[i]-max(close[i],o) + lower_wick = min(close[i],o)-low[i] + max_wick = max(upper_wick, lower_wick) + avg_rng = 0.0 + for j in range(i-period+1, i+1): avg_rng += high[j]-low[j] + avg_rng /= period + out[i] = max_wick/avg_rng if avg_rng > 0 else 0.0 + return out + +@nb.njit(cache=True) +def micro_fvg(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(2, n): + bull = low[i]-high[i-2]; bear = low[i-2]-high[i] + if bull > 0: out[i] = bull/close[i]*10000 if close[i] > 0 else 0.0 + elif bear > 0: out[i] = -bear/close[i]*10000 if close[i] > 0 else 0.0 + else: out[i] = 0.0 + return out + +@nb.njit(cache=True) +def micro_liq_sweep(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period+1, n): + ph = -1e18; pl = 1e18 + for j in range(i-period, i): + if high[j] > ph: ph = high[j] + if low[j] < pl: pl = low[j] + if high[i] > ph and close[i] < ph: out[i] = 1.0 + elif low[i] < pl and close[i] > pl: out[i] = -1.0 + else: out[i] = 0.0 + return out + +# ═══════════════════════════════════════════════════════════════════════════ +# ADVANCED MOMENTUM (IDs 98-103) +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def trend_breakout(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + hi = -1e18; lo = 1e18; ar = 0.0 + for j in range(i-period+1, i): + if high[j] > hi: hi = high[j] + if low[j] < lo: lo = low[j] + for j in range(i-period+1, i+1): ar += high[j]-low[j] + ar /= period + if ar > 0: + if close[i] > hi: out[i] = (close[i]-hi)/ar + elif close[i] < lo: out[i] = (close[i]-lo)/ar + else: out[i] = 0.0 + return out + +@nb.njit(cache=True) +def trend_pullback(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + hi = -1e18; lo = 1e18; ar = 0.0 + for j in range(i-period+1, i+1): + if high[j] > hi: hi = high[j] + if low[j] < lo: lo = low[j] + ar += high[j]-low[j] + ar /= period + mid = (hi+lo)/2.0 + out[i] = (close[i]-mid)/ar if ar > 0 else 0.0 + return out + +@nb.njit(cache=True) +def mom_velocity(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + x_mean = (period-1)/2.0; x_var = 0.0 + for j in range(period): x_var += (j-x_mean)**2 + for i in range(period, n): + y_mean = 0.0 + for j in range(period): y_mean += close[i-period+1+j] + y_mean /= period + slope = 0.0 + for j in range(period): slope += (j-x_mean)*(close[i-period+1+j]-y_mean) + slope /= x_var if x_var > 0 else 1.0 + out[i] = slope/y_mean*10000 if y_mean > 0 else 0.0 + return out + +@nb.njit(cache=True) +def mom_acceleration(close, high, low, volume, period, p1): + vel = mom_velocity(close, high, low, volume, period, p1) + n = len(close); out = np.full(n, np.nan) + for i in range(1, n): + if not np.isnan(vel[i]) and not np.isnan(vel[i-1]): + out[i] = vel[i]-vel[i-1] + return out + +@nb.njit(cache=True) +def mom_composite(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + ps = max(period//4, 1); pm = max(period//2, 2); pl = period + for i in range(pl, n): + rs = (close[i]-close[i-ps])/close[i-ps] if close[i-ps] > 0 else 0 + rm = (close[i]-close[i-pm])/close[i-pm] if close[i-pm] > 0 else 0 + rl = (close[i]-close[i-pl])/close[i-pl] if close[i-pl] > 0 else 0 + out[i] = (rs+rm+rl)/3.0*10000 + return out + +@nb.njit(cache=True) +def mom_normalized_roc(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period+1, n): + if close[i-period] == 0: continue + roc = (close[i]-close[i-period])/close[i-period] + m = 0.0 + for j in range(period): + m += (close[i-period+j+1]-close[i-period+j])/close[i-period+j] if close[i-period+j] > 0 else 0 + m /= period; s = 0.0 + for j in range(period): + r = (close[i-period+j+1]-close[i-period+j])/close[i-period+j] if close[i-period+j] > 0 else 0 + s += (r-m)**2 + std = math.sqrt(s/(period-1)) if period > 1 else 1e-10 + out[i] = roc/std if std > 0 else 0.0 + return out + +# ═══════════════════════════════════════════════════════════════════════════ +# CROSS-INDICATOR FEATURES (IDs 104-107) +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def cross_price_vs_ema(close, high, low, volume, period, p1): + n = len(close); alpha = 2.0/(period+1) + ema = np.full(n, np.nan) + s = 0.0 + for j in range(period): s += close[j] + ema[period-1] = s/period + for i in range(period, n): ema[i] = alpha*close[i]+(1-alpha)*ema[i-1] + tr = np.empty(n); tr[0] = high[0]-low[0] + for i in range(1, n): tr[i] = max(high[i]-low[i], max(abs(high[i]-close[i-1]), abs(low[i]-close[i-1]))) + atr = np.full(n, np.nan) + for i in range(period-1, n): + s = 0.0 + for j in range(max(i-period+1,0), i+1): s += tr[j] + atr[i] = s/min(period, i+1) + out = np.full(n, np.nan) + for i in range(period, n): + if not np.isnan(ema[i]) and not np.isnan(atr[i]) and atr[i] > 0: + out[i] = (close[i]-ema[i])/atr[i] + return out + +@nb.njit(cache=True) +def cross_ema_spread(close, high, low, volume, period, p1): + fp = max(period//3, 2); n = len(close) + af = 2.0/(fp+1); as_ = 2.0/(period+1) + ef = np.full(n, np.nan); es = np.full(n, np.nan) + sf = 0.0; ss = 0.0 + for j in range(fp): sf += close[j] + ef[fp-1] = sf/fp + for j in range(period): ss += close[j] + es[period-1] = ss/period + for i in range(fp, n): ef[i] = af*close[i]+(1-af)*ef[i-1] + for i in range(period, n): es[i] = as_*close[i]+(1-as_)*es[i-1] + out = np.full(n, np.nan) + for i in range(period, n): + if not np.isnan(ef[i]) and not np.isnan(es[i]) and close[i] > 0: + out[i] = (ef[i]-es[i])/close[i]*10000 + return out + +@nb.njit(cache=True) +def cross_mom_x_vol(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + roc = (close[i]-close[i-period])/close[i-period] if close[i-period] > 0 else 0 + va = 0.0 + for j in range(i-period+1, i+1): va += volume[j] + va /= period + vr = volume[i]/va if va > 0 else 1.0 + out[i] = roc*vr*10000 + return out + +@nb.njit(cache=True) +def cross_vol_adj_mom(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period+1, n): + if close[i-period] == 0: continue + roc = (close[i]-close[i-period])/close[i-period] + m = 0.0 + for j in range(period): + if close[i-period+j] > 0: m += math.log(close[i-period+j+1]/close[i-period+j]) + m /= period; s = 0.0 + for j in range(period): + if close[i-period+j] > 0: + lr = math.log(close[i-period+j+1]/close[i-period+j]); s += (lr-m)**2 + std = math.sqrt(s/(period-1)) if period > 1 else 1e-10 + out[i] = roc/std if std > 0 else 0.0 + return out + +# ═══════════════════════════════════════════════════════════════════════════ +# TIME FEATURES (IDs 109-110) +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def time_bars_since_high(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + mx = -1e18; idx = 0 + for j in range(period): + if high[i-period+1+j] > mx: mx = high[i-period+1+j]; idx = j + out[i] = float(period-1-idx) + return out + +@nb.njit(cache=True) +def time_bars_since_low(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + mn = 1e18; idx = 0 + for j in range(period): + if low[i-period+1+j] < mn: mn = low[i-period+1+j]; idx = j + out[i] = float(period-1-idx) + return out + +# ═══════════════════════════════════════════════════════════════════════════ +# DEPTH: PIVOT DISTANCE (ID 123) +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def pivot_distance(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + hh = -1e18; ll = 1e18; atr_sum = 0.0 + for j in range(i-period+1, i+1): + if high[j] > hh: hh = high[j] + if low[j] < ll: ll = low[j] + atr_sum += high[j]-low[j] + pivot = (hh+ll+close[i])/3.0; atr = atr_sum/period + out[i] = (close[i]-pivot)/atr if atr > 0 else 0.0 + return out + +# ═══════════════════════════════════════════════════════════════════════════ +# EVENT-STATE DETECTORS (IDs 135-141) +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def event_fresh_breakout(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + last_up = -1000; last_dn = -1000 + for i in range(period, n): + hh = -1e18; ll = 1e18 + for j in range(i-period, i): + if high[j] > hh: hh = high[j] + if low[j] < ll: ll = low[j] + if close[i] > hh: last_up = i + elif close[i] < ll: last_dn = i + if last_up > last_dn: out[i] = float(i-last_up) + elif last_dn > last_up: out[i] = -float(i-last_dn) + else: out[i] = float(period) + return out + +@nb.njit(cache=True) +def event_failed_breakout(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period+1, n): + hh = -1e18; ll = 1e18 + for j in range(i-period, i): + if high[j] > hh: hh = high[j] + if low[j] < ll: ll = low[j] + if high[i] > hh and close[i] <= hh: out[i] = 1.0 + elif low[i] < ll and close[i] >= ll: out[i] = -1.0 + else: out[i] = 0.0 + return out + +@nb.njit(cache=True) +def event_first_pullback(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + breakout_level = np.nan; breakout_dir = 0 + for i in range(period, n): + hh = -1e18; ll = 1e18; ar = 0.0 + for j in range(i-period, i): + if high[j] > hh: hh = high[j] + if low[j] < ll: ll = low[j] + ar += high[j]-low[j] + ar /= period + if close[i] > hh: breakout_level = hh; breakout_dir = 1 + elif close[i] < ll: breakout_level = ll; breakout_dir = -1 + if not np.isnan(breakout_level) and ar > 0: + out[i] = (close[i]-breakout_level)/ar*breakout_dir + return out + +@nb.njit(cache=True) +def event_vol_expansion(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + avg_rng = 0.0 + for j in range(i-period+1, i): avg_rng += high[j]-low[j] + avg_rng /= (period-1) if period > 1 else 1 + out[i] = (high[i]-low[i])/avg_rng if avg_rng > 0 else 1.0 + return out + +@nb.njit(cache=True) +def event_inside_bar(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(1, n): + if high[i] <= high[i-1] and low[i] >= low[i-1]: out[i] = 1.0 + elif high[i] >= high[i-1] and low[i] <= low[i-1]: out[i] = -1.0 + else: out[i] = 0.0 + return out + +@nb.njit(cache=True) +def event_compression_release(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + min_rng = 1e18 + for j in range(i-period+1, i): + rng = high[j]-low[j] + if rng < min_rng: min_rng = rng + out[i] = (high[i]-low[i])/min_rng if min_rng > 0 else 1.0 + return out + +@nb.njit(cache=True) +def event_sweep_reclaim(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period+1, n): + hh = -1e18; ll = 1e18; ar = 0.0 + for j in range(i-period, i): + if high[j] > hh: hh = high[j] + if low[j] < ll: ll = low[j] + ar += high[j]-low[j] + ar /= period + if ar <= 0: out[i] = 0.0; continue + if high[i] > hh and close[i] < hh: out[i] = (high[i]-hh)/ar + elif low[i] < ll and close[i] > ll: out[i] = -(ll-low[i])/ar + else: out[i] = 0.0 + return out + +# ═══════════════════════════════════════════════════════════════════════════ +# RELATIVE-POSITION FEATURES (IDs 142-147) +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def relpos_close_in_range(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(n): + rng = high[i]-low[i] + out[i] = (close[i]-low[i])/rng if rng > 0 else 0.5 + return out + +@nb.njit(cache=True) +def relpos_close_in_rolling_range(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + hh = -1e18; ll = 1e18 + for j in range(i-period+1, i+1): + if high[j] > hh: hh = high[j] + if low[j] < ll: ll = low[j] + rng = hh-ll + out[i] = (close[i]-ll)/rng if rng > 0 else 0.5 + return out + +@nb.njit(cache=True) +def relpos_dist_recent_high(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + hh = -1e18; ar = 0.0 + for j in range(i-period+1, i+1): + if high[j] > hh: hh = high[j] + ar += high[j]-low[j] + ar /= period + out[i] = (close[i]-hh)/ar if ar > 0 else 0.0 + return out + +@nb.njit(cache=True) +def relpos_dist_recent_low(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + ll = 1e18; ar = 0.0 + for j in range(i-period+1, i+1): + if low[j] < ll: ll = low[j] + ar += high[j]-low[j] + ar /= period + out[i] = (close[i]-ll)/ar if ar > 0 else 0.0 + return out + +@nb.njit(cache=True) +def relpos_channel_position(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + x_mean = (period-1)/2.0; x_var = 0.0 + for j in range(period): x_var += (j-x_mean)**2 + for i in range(period-1, n): + y_mean = 0.0 + for j in range(period): y_mean += close[i-period+1+j] + y_mean /= period + slope = 0.0 + for j in range(period): slope += (j-x_mean)*(close[i-period+1+j]-y_mean) + slope /= x_var if x_var > 0 else 1.0 + intercept = y_mean - slope*x_mean + ss = 0.0 + for j in range(period): + pred = slope*j + intercept; ss += (close[i-period+1+j]-pred)**2 + std = math.sqrt(ss/(period-1)) if period > 1 else 1e-10 + reg_val = slope*(period-1)+intercept + out[i] = (close[i]-reg_val)/std if std > 0 else 0.0 + return out + +@nb.njit(cache=True) +def relpos_open_close_vs_prior(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + ar = 0.0 + for j in range(i-period+1, i+1): ar += high[j]-low[j] + ar /= period + if ar > 0 and i > 0: out[i] = (close[i]-close[i-1])/ar + return out + +# ═══════════════════════════════════════════════════════════════════════════ +# MARKET QUALITY / TRADABILITY (IDs 150-158) +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def quality_chop_index(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + atr_sum = 0.0; hh = -1e18; ll = 1e18 + for j in range(i-period+1, i+1): + tr = max(high[j]-low[j], max(abs(high[j]-close[j-1]), abs(low[j]-close[j-1]))) if j > 0 else high[j]-low[j] + atr_sum += tr + if high[j] > hh: hh = high[j] + if low[j] < ll: ll = low[j] + rng = hh-ll + if rng > 0 and atr_sum > 0: + out[i] = 100.0*math.log10(atr_sum/rng)/math.log10(period) + return out + +@nb.njit(cache=True) +def quality_candle_overlap(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + overlap_sum = 0.0; range_sum = 0.0 + for j in range(i-period+2, i+1): + overlap = max(0, min(high[j], high[j-1])-max(low[j], low[j-1])) + total_rng = max(high[j], high[j-1])-min(low[j], low[j-1]) + overlap_sum += overlap; range_sum += total_rng + out[i] = overlap_sum/range_sum if range_sum > 0 else 0.5 + return out + +@nb.njit(cache=True) +def quality_noise_ratio(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + net = abs(close[i]-close[i-period]); path = 0.0 + for j in range(i-period+1, i+1): path += high[j]-low[j] + out[i] = path/net if net > 0 else float(period) + return out + +@nb.njit(cache=True) +def quality_wick_instability(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + wick_sum = 0.0; range_sum = 0.0 + for j in range(i-period+1, i+1): + o = close[j-1] if j > 0 else close[j] + body = abs(close[j]-o); rng = high[j]-low[j] + wick_sum += (rng-body); range_sum += rng + out[i] = wick_sum/range_sum if range_sum > 0 else 0.5 + return out + +@nb.njit(cache=True) +def quality_false_break_freq(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + lookback = max(period, 10) + for i in range(lookback+period, n): + false_breaks = 0 + for k in range(i-lookback+1, i+1): + hh = -1e18; ll = 1e18 + for j in range(k-period, k): + if high[j] > hh: hh = high[j] + if low[j] < ll: ll = low[j] + if (high[k] > hh and close[k] <= hh) or (low[k] < ll and close[k] >= ll): + false_breaks += 1 + out[i] = float(false_breaks)/lookback + return out + +@nb.njit(cache=True) +def quality_spread_proxy(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + s = 0.0 + for j in range(i-period+1, i+1): + s += (high[j]-low[j])/close[j] if close[j] > 0 else 0 + out[i] = 100.0*s/period + return out + +@nb.njit(cache=True) +def quality_directional_clean(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + net = close[i]-close[i-period]; total = 0.0 + for j in range(i-period+1, i+1): total += abs(close[j]-close[j-1]) + out[i] = abs(net)/total if total > 0 else 0.0 + return out + +@nb.njit(cache=True) +def quality_reversal_freq(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period+1, n): + reversals = 0 + for j in range(i-period+2, i+1): + d1 = close[j]-close[j-1]; d2 = close[j-1]-close[j-2] + if (d1 > 0 and d2 < 0) or (d1 < 0 and d2 > 0): reversals += 1 + out[i] = float(reversals)/(period-1) if period > 1 else 0.5 + return out + +@nb.njit(cache=True) +def quality_median_excursion(close, high, low, volume, period, p1): + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + excursions = np.empty(period) + for j in range(period): + idx = i-period+1+j; excursions[j] = high[idx]-close[idx] + excursions.sort() + out[i] = excursions[period//2] + return out + +# ═══════════════════════════════════════════════════════════════════════════ +# OSCILLATOR STATE / BEHAVIOR (IDs 160-167) +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def _rsi_internal(close, period): + n = len(close); out = np.full(n, np.nan) + if n < period + 1: return out + ag = 0.0; al = 0.0 + for i in range(1, period+1): + d = close[i]-close[i-1] + if d > 0: ag += d + else: al -= d + ag /= period; al /= period + out[period] = 100.0-100.0/(1.0+ag/al) if al > 0 else 100.0 + alpha = 1.0/period + for i in range(period+1, n): + d = close[i]-close[i-1] + g = d if d > 0 else 0.0; lo = -d if d < 0 else 0.0 + ag = alpha*g + (1-alpha)*ag; al = alpha*lo + (1-alpha)*al + out[i] = 100.0-100.0/(1.0+ag/al) if al > 0 else 100.0 + return out + +@nb.njit(cache=True) +def osc_rsi_slope(close, high, low, volume, period, p1): + rsi = _rsi_internal(close, period) + n = len(close); out = np.full(n, np.nan) + for i in range(3, n): + if not np.isnan(rsi[i]) and not np.isnan(rsi[i-3]): + out[i] = (rsi[i]-rsi[i-3])/3.0 + return out + +@nb.njit(cache=True) +def osc_rsi_dist_50(close, high, low, volume, period, p1): + rsi = _rsi_internal(close, period) + n = len(close); out = np.full(n, np.nan) + for i in range(n): + if not np.isnan(rsi[i]): out[i] = rsi[i]-50.0 + return out + +@nb.njit(cache=True) +def osc_rsi_divergence(close, high, low, volume, period, p1): + rsi = _rsi_internal(close, period) + n = len(close); out = np.full(n, np.nan) + lookback = max(int(p1), 5) if p1 > 0 else 5 + for i in range(period+lookback, n): + if np.isnan(rsi[i]) or np.isnan(rsi[i-lookback]): continue + price_slope = (close[i]-close[i-lookback])/close[i-lookback] if close[i-lookback] > 0 else 0 + rsi_slope = (rsi[i]-rsi[i-lookback])/100.0 + out[i] = price_slope-rsi_slope + return out + +@nb.njit(cache=True) +def osc_macd_slope(close, high, low, volume, period, p1): + n = len(close); fast_p = max(period//2, 2) + alpha_f = 2.0/(fast_p+1); alpha_s = 2.0/(period+1) + ef = np.full(n, np.nan); es = np.full(n, np.nan) + sf = 0.0; ss = 0.0 + for j in range(fast_p): sf += close[j] + ef[fast_p-1] = sf/fast_p + for j in range(period): ss += close[j] + es[period-1] = ss/period + for i in range(fast_p, n): ef[i] = alpha_f*close[i]+(1-alpha_f)*ef[i-1] + for i in range(period, n): es[i] = alpha_s*close[i]+(1-alpha_s)*es[i-1] + macd = np.full(n, np.nan) + for i in range(n): + if not np.isnan(ef[i]) and not np.isnan(es[i]): macd[i] = ef[i]-es[i] + alpha_sig = 2.0/10.0; sig = np.full(n, np.nan); first = -1 + for i in range(n): + if not np.isnan(macd[i]): + if first < 0: first = i; sig[i] = macd[i] + else: sig[i] = alpha_sig*macd[i]+(1-alpha_sig)*sig[i-1] + hist = np.full(n, np.nan) + for i in range(n): + if not np.isnan(macd[i]) and not np.isnan(sig[i]): hist[i] = macd[i]-sig[i] + out = np.full(n, np.nan) + for i in range(3, n): + if not np.isnan(hist[i]) and not np.isnan(hist[i-3]): + out[i] = (hist[i]-hist[i-3])/3.0 + return out + +@nb.njit(cache=True) +def osc_macd_divergence(close, high, low, volume, period, p1): + n = len(close); fast_p = max(period//2, 2) + alpha_f = 2.0/(fast_p+1); alpha_s = 2.0/(period+1) + ef = np.full(n, np.nan); es = np.full(n, np.nan) + sf = 0.0; ss = 0.0 + for j in range(fast_p): sf += close[j] + ef[fast_p-1] = sf/fast_p + for j in range(period): ss += close[j] + es[period-1] = ss/period + for i in range(fast_p, n): ef[i] = alpha_f*close[i]+(1-alpha_f)*ef[i-1] + for i in range(period, n): es[i] = alpha_s*close[i]+(1-alpha_s)*es[i-1] + macd = np.full(n, np.nan) + for i in range(n): + if not np.isnan(ef[i]) and not np.isnan(es[i]): macd[i] = ef[i]-es[i] + out = np.full(n, np.nan) + lookback = 5 + for i in range(period+lookback, n): + if np.isnan(macd[i]) or np.isnan(macd[i-lookback]): continue + ps = (close[i]-close[i-lookback])/close[i-lookback] if close[i-lookback] > 0 else 0 + ms = macd[i]-macd[i-lookback] + ms_norm = ms/close[i]*1000 if close[i] > 0 else 0 + out[i] = ps*1000-ms_norm + return out + +@nb.njit(cache=True) +def osc_time_since_ob(close, high, low, volume, period, p1): + rsi = _rsi_internal(close, period) + n = len(close); out = np.full(n, np.nan); last_ob = -1000 + for i in range(n): + if not np.isnan(rsi[i]) and rsi[i] > 70: last_ob = i + if last_ob >= 0: out[i] = float(i-last_ob) + return out + +@nb.njit(cache=True) +def osc_time_since_os(close, high, low, volume, period, p1): + rsi = _rsi_internal(close, period) + n = len(close); out = np.full(n, np.nan); last_os = -1000 + for i in range(n): + if not np.isnan(rsi[i]) and rsi[i] < 30: last_os = i + if last_os >= 0: out[i] = float(i-last_os) + return out + +@nb.njit(cache=True) +def osc_exhaustion_score(close, high, low, volume, period, p1): + rsi = _rsi_internal(close, period) + n = len(close); out = np.full(n, np.nan) + for i in range(period+3, n): + if np.isnan(rsi[i]): continue + rsi_ext = abs(rsi[i]-50.0)/50.0 + if close[i-1] > 0 and close[i-4] > 0: + roc_now = (close[i]-close[i-1])/close[i-1] + roc_prev = (close[i-3]-close[i-4])/close[i-4] + mom_decay = 1.0 if abs(roc_now) < abs(roc_prev) and roc_now*roc_prev > 0 else 0.0 + else: mom_decay = 0.0 + vol_avg = 0.0 + for j in range(i-period+1, i): vol_avg += volume[j] + vol_avg /= (period-1) if period > 1 else 1 + vol_spike = volume[i]/vol_avg if vol_avg > 0 else 1.0 + vol_score = min(vol_spike/2.0, 1.0) + out[i] = (rsi_ext*0.4+mom_decay*0.3+vol_score*0.3)*100 + return out + +# ═══════════════════════════════════════════════════════════════════════════ +# SCALP INDICATORS — fast signals for sub-hour trading +# ═══════════════════════════════════════════════════════════════════════════ + +@nb.njit(cache=True) +def scalp_tick_imbalance(close, high, low, volume, period, p1): + """Count of up-bars minus down-bars in last N bars. Normalized to [-100, 100].""" + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + up = 0; dn = 0 + for j in range(i - period + 1, i + 1): + if close[j] > close[j-1]: up += 1 + elif close[j] < close[j-1]: dn += 1 + out[i] = (up - dn) / period * 100 + return out + +@nb.njit(cache=True) +def scalp_speed(close, high, low, volume, period, p1): + """Price change per bar — momentum speed. Normalized by ATR.""" + n = len(close); out = np.full(n, np.nan) + for i in range(period + 1, n): + atr = 0.0 + for j in range(i - period + 1, i + 1): + tr = max(high[j] - low[j], abs(high[j] - close[j-1]), abs(low[j] - close[j-1])) + atr += tr + atr /= period + if atr > 0: + speed = (close[i] - close[i - period]) / (period * atr) + out[i] = speed * 100 + return out + +@nb.njit(cache=True) +def scalp_range_position(close, high, low, volume, period, p1): + """Where close sits in recent N-bar range. 0=at low, 100=at high.""" + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + hi = high[i]; lo = low[i] + for j in range(i - period + 1, i): + if high[j] > hi: hi = high[j] + if low[j] < lo: lo = low[j] + rng = hi - lo + if rng > 0: + out[i] = (close[i] - lo) / rng * 100 + return out + +@nb.njit(cache=True) +def scalp_consecutive(close, high, low, volume, period, p1): + """Number of consecutive same-direction closes. Positive=up, negative=down.""" + n = len(close); out = np.full(n, np.nan) + for i in range(1, n): + count = 0 + direction = 1 if close[i] > close[i-1] else -1 + j = i + while j > 0 and count < 20: + if close[j] > close[j-1]: + if direction == 1: count += 1 + else: break + elif close[j] < close[j-1]: + if direction == -1: count += 1 + else: break + j -= 1 + out[i] = direction * count + return out + +@nb.njit(cache=True) +def scalp_wick_rejection(close, high, low, volume, period, p1): + """Wick size relative to body. Large wick + small body = rejection signal. + Positive = upper wick (bearish rejection), Negative = lower wick (bullish rejection).""" + n = len(close); out = np.full(n, np.nan) + for i in range(1, n): + body = abs(close[i] - close[i-1]) if i > 0 else abs(close[i] - close[i]) + rng = high[i] - low[i] + if rng > 0 and body > 0: + upper_wick = high[i] - max(close[i], close[i-1] if i > 0 else close[i]) + lower_wick = min(close[i], close[i-1] if i > 0 else close[i]) - low[i] + if upper_wick > lower_wick: + out[i] = upper_wick / rng * 100 # bearish rejection + else: + out[i] = -lower_wick / rng * 100 # bullish rejection + return out + +@nb.njit(cache=True) +def scalp_volume_spike(close, high, low, volume, period, p1): + """Current volume / average volume. >200 = spike opportunity.""" + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + avg = 0.0 + for j in range(i - period, i): + avg += volume[j] + avg /= period + if avg > 0: + out[i] = volume[i] / avg * 100 + return out + +@nb.njit(cache=True) +def scalp_micro_momentum(close, high, low, volume, period, p1): + """Ultra-short momentum: sum of last N bar returns. Captures micro-trends.""" + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + mom = 0.0 + for j in range(i - period + 1, i + 1): + if close[j-1] > 0: + mom += (close[j] - close[j-1]) / close[j-1] + out[i] = mom * 10000 # in bps + return out + +@nb.njit(cache=True) +def scalp_volatility_ratio(close, high, low, volume, period, p1): + """Short-term vol / long-term vol. >1 = expanding, <1 = contracting.""" + n = len(close); out = np.full(n, np.nan) + long_period = period * 4 + for i in range(long_period, n): + short_vol = 0.0; long_vol = 0.0 + for j in range(i - period + 1, i + 1): + if close[j-1] > 0: + r = (close[j] - close[j-1]) / close[j-1] + short_vol += r * r + short_vol = (short_vol / period) ** 0.5 + for j in range(i - long_period + 1, i + 1): + if close[j-1] > 0: + r = (close[j] - close[j-1]) / close[j-1] + long_vol += r * r + long_vol = (long_vol / long_period) ** 0.5 + if long_vol > 0: + out[i] = short_vol / long_vol * 100 + return out + +@nb.njit(cache=True) +def scalp_mean_reversion(close, high, low, volume, period, p1): + """Distance from rolling mean, normalized by std. Z-score-like for fast mean reversion.""" + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + mean = 0.0 + for j in range(i - period + 1, i + 1): mean += close[j] + mean /= period + std = 0.0 + for j in range(i - period + 1, i + 1): std += (close[j] - mean) ** 2 + std = (std / period) ** 0.5 + if std > 0: + out[i] = (close[i] - mean) / std * 33 # scaled so ±3 std ≈ ±100 + return out + +@nb.njit(cache=True) +def scalp_bar_energy(close, high, low, volume, period, p1): + """Volume × range — measures how much 'energy' each bar has. Averaged over period.""" + n = len(close); out = np.full(n, np.nan) + for i in range(period, n): + avg = 0.0 + for j in range(i - period + 1, i + 1): + rng = (high[j] - low[j]) / close[j] if close[j] > 0 else 0 + avg += rng * volume[j] + avg /= period + current = (high[i] - low[i]) / close[i] * volume[i] if close[i] > 0 else 0 + if avg > 0: + out[i] = current / avg * 100 + return out + + +# ====================================================================== +""" +Cell 2b: Pool builder + indicator cache pre-computation. + +Builds the FAST_POOL (same as fast_engine.py build_fast_pool), extracts focused pools, +then pre-computes ALL unique indicator variants into cache arrays for GPU upload. +""" + + +# (build_fast_pool and pool-config code removed — not needed for CPU cache builder) + +# ── Compute dispatcher (matches fast_engine.py compute()) ── +def compute_indicator(ind_id, close, high, low, volume, period, p1): + """CPU dispatcher — calls the right inlined numba function.""" + p = int(period) + # Moving Averages + if ind_id == 0: return ma_sma(close, p, p1) + elif ind_id == 1: return ma_ema(close, p, p1) + elif ind_id == 2: return ma_wma(close, p, p1) + elif ind_id == 3: return ma_hma(close, p, p1) + elif ind_id == 4: return ma_dema(close, p, p1) + elif ind_id == 5: return ma_tema(close, p, p1) + elif ind_id == 6: return ma_kama(close, p, p1) + elif ind_id == 7: return ma_ehlers_ss(close, p, p1) + elif ind_id == 8: return ma_mcginley(close, p, p1) + elif ind_id == 9: return ma_jma(close, p, p1) + elif ind_id == 10: return ma_t3(close, p, p1) + elif ind_id == 11: return ma_alma(close, p, p1) + elif ind_id == 12: return ma_zlema(close, p, p1) + elif ind_id == 13: return ma_vidya(close, p, p1) + elif ind_id == 14: return ma_frama(close, p, p1) + elif ind_id == 15: return ma_lsma(close, p, p1) + elif ind_id == 16: return ma_swma(close, p, p1) + elif ind_id == 17: return bb_upper(close, p, p1 if p1 > 0 else 2.0) + elif ind_id == 18: return bb_lower(close, p, p1 if p1 > 0 else 2.0) + elif ind_id == 19: return supertrend(close, high, low, p, p1 if p1 > 0 else 3.0) + elif ind_id == 20: return donch_upper(high, p, p1) + elif ind_id == 21: return donch_lower(low, p, p1) + elif ind_id == 22: return (donch_upper(high, p, p1) + donch_lower(low, p, p1)) / 2.0 + elif ind_id == 23: return kelt_upper(close, high, low, p, p1 if p1 > 0 else 1.5) + elif ind_id == 24: return kelt_lower(close, high, low, p, p1 if p1 > 0 else 1.5) + elif ind_id == 25: return ma_ema(close, p, p1) + elif ind_id == 26: return ichimoku_midline(high, low, min(p, 9)) + elif ind_id == 27: return ichimoku_midline(high, low, p) + elif ind_id == 28: return psar(close, high, low, p, p1 if p1 > 0 else 0.02) + # Oscillators + elif ind_id == 30: return osc_rsi(close, p, p1) + elif ind_id == 31: return osc_stoch_k(close, high, low, p, p1) + elif ind_id == 32: return osc_stoch_d(close, high, low, p, p1) + elif ind_id == 33: return osc_cci(close, high, low, p, p1) + elif ind_id == 34: return osc_williams_r(close, high, low, p, p1) + elif ind_id == 35: return osc_roc(close, p, p1) + elif ind_id == 36: return osc_cmo(close, p, p1) + elif ind_id == 37: return osc_trix(close, p, p1) + elif ind_id == 38: return osc_ppo(close, p, p1) + elif ind_id == 39: return osc_macd_hist(close, p, p1) + elif ind_id == 40: return osc_mfi(close, high, low, volume, p, p1) + elif ind_id == 41: return osc_dpo(close, p, p1) + elif ind_id == 42: return norm_pctile_rank(close, p, p1) + elif ind_id == 43: return norm_zscore(close, p, p1) + elif ind_id == 44: return norm_minmax(close, p, p1) + # Volatility / Filter + elif ind_id == 50: return vol_atr(close, high, low, p, p1) + elif ind_id == 51: return vol_atr_pct(close, high, low, p, p1) + elif ind_id == 52: return vol_atr_zscore(close, high, low, p, p1) + elif ind_id == 53: return vol_compression(close, high, low, p, p1) + elif ind_id == 54: return vol_of_vol(close, high, low, p, p1) + elif ind_id == 55: return vol_parkinson(close, high, low, p, p1) + elif ind_id == 56: return vol_garman_klass(close, high, low, p, p1) + elif ind_id == 57: return vol_rogers_satchell(close, high, low, p, p1) + elif ind_id == 58: return vol_realized(close, high, low, p, p1) + elif ind_id == 59: return vol_range_pctile(close, high, low, p, p1) + elif ind_id == 60: return vol_tr_momentum(close, high, low, p, p1) + elif ind_id == 61: return norm_vol_zscore(close, high, low, volume, p, p1) + elif ind_id == 62: return micro_vol_clustering(close, high, low, volume, p, p1) + elif ind_id == 63: return micro_vol_delta(close, high, low, volume, p, p1) + # Trend / Regime + elif ind_id == 70: return adx(close, high, low, p, p1) + elif ind_id == 71: return aroon_up(high, p, p1) + elif ind_id == 72: return aroon_down(low, p, p1) + elif ind_id == 73: return linreg_slope(close, p, p1) + elif ind_id == 74: return linreg_r2(close, p, p1) + elif ind_id == 75: return trend_efficiency(close, p, p1) + elif ind_id == 76: return trend_angle(close, p, p1) + elif ind_id == 77: return trend_duration(close, p, p1) + elif ind_id == 78: return regime_hurst(close, p, p1) + elif ind_id == 79: return regime_variance_ratio(close, p, p1) + elif ind_id == 80: return regime_fractal_dim(close, p, p1) + elif ind_id == 81: return regime_trend_persist(close, p, p1) + elif ind_id == 82: return regime_autocorr(close, p, p1) + elif ind_id == 83: return micro_trend_struct(close, high, low, p, p1) + elif ind_id == 168: return trend_lhll_score(close, high, low, p, p1) + # Depth: Pivot / Reference + elif ind_id == 120: return pivot_classic(close, high, low, p, p1) + elif ind_id == 121: return pivot_r1(close, high, low, p, p1) + elif ind_id == 122: return pivot_s1(close, high, low, p, p1) + elif ind_id == 124: return prev_period_high(close, high, low, p, p1) + elif ind_id == 125: return prev_period_low(close, high, low, p, p1) + elif ind_id == 126: return prev_period_close(close, high, low, p, p1) + elif ind_id == 127: return rolling_median(close, p, p1) + elif ind_id == 128: return linreg_channel_upper(close, p, p1) + elif ind_id == 129: return linreg_channel_lower(close, p, p1) + elif ind_id == 130: return quantile_band_upper(close, p, p1) + elif ind_id == 131: return quantile_band_lower(close, p, p1) + # Filter extras + elif ind_id == 111: return entropy_shannon(close, p, p1) + elif ind_id == 112: return regime_kurtosis(close, p, p1) + elif ind_id == 113: return regime_halflife(close, p, p1) + elif ind_id == 114: return regime_dc_events(close, p, p1) + elif ind_id == 115: return cross_ma_compression(close, p, p1) + elif ind_id == 116: return regime_skewness(close, p, p1) + elif ind_id == 117: return time_hour_sin(p, len(close)) + elif ind_id == 118: return time_hour_cos(p, len(close)) + elif ind_id == 119: return time_session_vol(close, p, p1) + elif ind_id == 108: return norm_return_zscore(close, p, p1) + # Microstructure + elif ind_id == 90: return micro_body_ratio(close, high, low, volume, p, p1) + elif ind_id == 91: return micro_upper_wick(close, high, low, volume, p, p1) + elif ind_id == 92: return micro_lower_wick(close, high, low, volume, p, p1) + elif ind_id == 93: return micro_buy_pressure(close, high, low, volume, p, p1) + elif ind_id == 94: return micro_sell_pressure(close, high, low, volume, p, p1) + elif ind_id == 95: return micro_stop_hunt(close, high, low, volume, p, p1) + elif ind_id == 96: return micro_fvg(close, high, low, volume, p, p1) + elif ind_id == 97: return micro_liq_sweep(close, high, low, volume, p, p1) + # Momentum / Trend + elif ind_id == 98: return trend_breakout(close, high, low, volume, p, p1) + elif ind_id == 99: return trend_pullback(close, high, low, volume, p, p1) + elif ind_id == 100: return mom_velocity(close, high, low, volume, p, p1) + elif ind_id == 101: return mom_acceleration(close, high, low, volume, p, p1) + elif ind_id == 102: return mom_composite(close, high, low, volume, p, p1) + elif ind_id == 103: return mom_normalized_roc(close, high, low, volume, p, p1) + # Cross-Indicator + elif ind_id == 104: return cross_price_vs_ema(close, high, low, volume, p, p1) + elif ind_id == 105: return cross_ema_spread(close, high, low, volume, p, p1) + elif ind_id == 106: return cross_mom_x_vol(close, high, low, volume, p, p1) + elif ind_id == 107: return cross_vol_adj_mom(close, high, low, volume, p, p1) + # Time Features + elif ind_id == 109: return time_bars_since_high(close, high, low, volume, p, p1) + elif ind_id == 110: return time_bars_since_low(close, high, low, volume, p, p1) + # Depth: Pivot Distance + elif ind_id == 123: return pivot_distance(close, high, low, volume, p, p1) + # Event-State + elif ind_id == 135: return event_fresh_breakout(close, high, low, volume, p, p1) + elif ind_id == 136: return event_failed_breakout(close, high, low, volume, p, p1) + elif ind_id == 137: return event_first_pullback(close, high, low, volume, p, p1) + elif ind_id == 138: return event_vol_expansion(close, high, low, volume, p, p1) + elif ind_id == 139: return event_inside_bar(close, high, low, volume, p, p1) + elif ind_id == 140: return event_compression_release(close, high, low, volume, p, p1) + elif ind_id == 141: return event_sweep_reclaim(close, high, low, volume, p, p1) + # Relative Position + elif ind_id == 142: return relpos_close_in_range(close, high, low, volume, p, p1) + elif ind_id == 143: return relpos_close_in_rolling_range(close, high, low, volume, p, p1) + elif ind_id == 144: return relpos_dist_recent_high(close, high, low, volume, p, p1) + elif ind_id == 145: return relpos_dist_recent_low(close, high, low, volume, p, p1) + elif ind_id == 146: return relpos_channel_position(close, high, low, volume, p, p1) + elif ind_id == 147: return relpos_open_close_vs_prior(close, high, low, volume, p, p1) + # Market Quality + elif ind_id == 150: return quality_chop_index(close, high, low, volume, p, p1) + elif ind_id == 151: return quality_candle_overlap(close, high, low, volume, p, p1) + elif ind_id == 152: return quality_noise_ratio(close, high, low, volume, p, p1) + elif ind_id == 153: return quality_wick_instability(close, high, low, volume, p, p1) + elif ind_id == 154: return quality_false_break_freq(close, high, low, volume, p, p1) + elif ind_id == 155: return quality_spread_proxy(close, high, low, volume, p, p1) + elif ind_id == 156: return quality_directional_clean(close, high, low, volume, p, p1) + elif ind_id == 157: return quality_reversal_freq(close, high, low, volume, p, p1) + elif ind_id == 158: return quality_median_excursion(close, high, low, volume, p, p1) + # Oscillator State + elif ind_id == 160: return osc_rsi_slope(close, high, low, volume, p, p1) + elif ind_id == 161: return osc_rsi_dist_50(close, high, low, volume, p, p1) + elif ind_id == 162: return osc_rsi_divergence(close, high, low, volume, p, p1) + elif ind_id == 163: return osc_macd_slope(close, high, low, volume, p, p1) + elif ind_id == 164: return osc_macd_divergence(close, high, low, volume, p, p1) + elif ind_id == 165: return osc_time_since_ob(close, high, low, volume, p, p1) + elif ind_id == 166: return osc_time_since_os(close, high, low, volume, p, p1) + elif ind_id == 167: return osc_exhaustion_score(close, high, low, volume, p, p1) + # Scalp indicators (170-179) + elif ind_id == 170: return scalp_tick_imbalance(close, high, low, volume, p, p1) + elif ind_id == 171: return scalp_speed(close, high, low, volume, p, p1) + elif ind_id == 172: return scalp_range_position(close, high, low, volume, p, p1) + elif ind_id == 173: return scalp_consecutive(close, high, low, volume, p, p1) + elif ind_id == 174: return scalp_wick_rejection(close, high, low, volume, p, p1) + elif ind_id == 175: return scalp_volume_spike(close, high, low, volume, p, p1) + elif ind_id == 176: return scalp_micro_momentum(close, high, low, volume, p, p1) + elif ind_id == 177: return scalp_volatility_ratio(close, high, low, volume, p, p1) + elif ind_id == 178: return scalp_mean_reversion(close, high, low, volume, p, p1) + elif ind_id == 179: return scalp_bar_energy(close, high, low, volume, p, p1) + else: + return np.full(len(close), np.nan) diff --git a/control_plane/trading_studio/indicators/hs22_historical_registry_v1.json b/control_plane/trading_studio/indicators/hs22_historical_registry_v1.json new file mode 100644 index 0000000..f7c50a5 --- /dev/null +++ b/control_plane/trading_studio/indicators/hs22_historical_registry_v1.json @@ -0,0 +1 @@ +{"definition_count":145,"definitions":[{"alias_of":null,"behavior":"refuse_execution","indicator_id":0,"name":"SMA","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":1,"name":"EMA","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":2,"name":"WMA","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":3,"name":"HMA","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":4,"name":"DEMA","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":5,"name":"TEMA","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":6,"name":"KAMA","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":7,"name":"EHLERS_SS","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":8,"name":"MCGINLEY","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":9,"name":"JMA","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":10,"name":"T3","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":11,"name":"ALMA","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":12,"name":"ZLEMA","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":13,"name":"VIDYA","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":14,"name":"FRAMA","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":15,"name":"LSMA","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":16,"name":"SWMA","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":17,"name":"BB_UPPER","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":18,"name":"BB_LOWER","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":19,"name":"SUPERTREND","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":20,"name":"DONCHIAN_UPPER","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":21,"name":"DONCHIAN_LOWER","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":22,"name":"DONCHIAN_MID","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":23,"name":"KELTNER_UPPER","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":24,"name":"KELTNER_LOWER","role":"level","status":"unimplemented"},{"alias_of":1,"behavior":"historical_alias; execution_refused","indicator_id":25,"name":"KELTNER_MID","role":"level","status":"alias"},{"alias_of":null,"behavior":"historical_alias; execution_refused","indicator_id":26,"name":"ICHIMOKU_TENKAN","role":"level","status":"alias"},{"alias_of":null,"behavior":"historical_alias; execution_refused","indicator_id":27,"name":"ICHIMOKU_KIJUN","role":"level","status":"alias"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":28,"name":"PSAR","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":30,"name":"RSI","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":31,"name":"STOCH_K","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":32,"name":"STOCH_D","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":33,"name":"CCI","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":34,"name":"WILLIAMS_R","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":35,"name":"ROC","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":36,"name":"CMO","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":37,"name":"TRIX","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":38,"name":"PPO","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":39,"name":"MACD_HIST","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":40,"name":"MFI","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":41,"name":"DPO","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":42,"name":"PCTILE_RANK","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":43,"name":"ZSCORE","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":44,"name":"MINMAX","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":50,"name":"ID_50","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":51,"name":"ID_51","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":52,"name":"VOL_ATR_ZSCORE","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":53,"name":"ID_53","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":54,"name":"ID_54","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":55,"name":"ID_55","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":56,"name":"ID_56","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":57,"name":"ID_57","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":58,"name":"ID_58","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":59,"name":"VOL_RANGE_PCTILE","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":60,"name":"VOL_TR_MOMENTUM","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":61,"name":"ID_61","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":62,"name":"ID_62","role":"trend","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":63,"name":"ID_63","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":70,"name":"ADX","role":"trend","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":71,"name":"AROON_UP","role":"trend","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":72,"name":"AROON_DOWN","role":"trend","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":73,"name":"LINREG_SLOPE","role":"trend","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":74,"name":"LINREG_R2","role":"trend","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":75,"name":"EFFICIENCY","role":"trend","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":76,"name":"ANGLE","role":"trend","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":77,"name":"DURATION","role":"trend","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":78,"name":"HURST","role":"trend","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":79,"name":"ID_79","role":"trend","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":80,"name":"FRACTAL_DIM","role":"trend","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":81,"name":"TREND_PERSIST","role":"trend","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":82,"name":"ID_82","role":"trend","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":83,"name":"MICRO_TREND_STRUCT","role":"trend","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":90,"name":"MICRO_BODY_RATIO","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":91,"name":"MICRO_UPPER_WICK","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":92,"name":"MICRO_LOWER_WICK","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":93,"name":"MICRO_BUY_PRESSURE","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":94,"name":"MICRO_SELL_PRESSURE","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":95,"name":"MICRO_STOP_HUNT","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":96,"name":"MICRO_FVG","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":97,"name":"MICRO_LIQ_SWEEP","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":98,"name":"TREND_BREAKOUT","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":99,"name":"TREND_PULLBACK","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":100,"name":"MOM_VELOCITY","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":101,"name":"MOM_ACCELERATION","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":102,"name":"MOM_COMPOSITE","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":103,"name":"MOM_NORMALIZED_ROC","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":104,"name":"CROSS_PRICE_VS_EMA","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":105,"name":"CROSS_EMA_SPREAD","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":106,"name":"CROSS_MOM_X_VOL","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":107,"name":"CROSS_VOL_ADJ_MOM","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":108,"name":"NORM_RETURN_ZSCORE","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":109,"name":"TIME_BARS_SINCE_HIGH","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":110,"name":"TIME_BARS_SINCE_LOW","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":111,"name":"ID_111","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":112,"name":"ID_112","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":113,"name":"ID_113","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":114,"name":"ID_114","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":115,"name":"ID_115","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":116,"name":"REGIME_SKEWNESS","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":117,"name":"ID_117","role":"trend","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":118,"name":"ID_118","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":119,"name":"ID_119","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":120,"name":"ID_120","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":121,"name":"ID_121","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":122,"name":"ID_122","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":123,"name":"ID_123","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":124,"name":"ID_124","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":125,"name":"ID_125","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":126,"name":"ID_126","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":127,"name":"ID_127","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":128,"name":"ID_128","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":129,"name":"ID_129","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":130,"name":"ID_130","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":131,"name":"ID_131","role":"level","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":135,"name":"ID_135","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":136,"name":"ID_136","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":137,"name":"ID_137","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":138,"name":"ID_138","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":139,"name":"ID_139","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":140,"name":"ID_140","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":141,"name":"ID_141","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":142,"name":"ID_142","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":143,"name":"ID_143","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":144,"name":"ID_144","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":145,"name":"ID_145","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":146,"name":"ID_146","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":147,"name":"ID_147","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":150,"name":"ID_150","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":151,"name":"ID_151","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":152,"name":"ID_152","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":153,"name":"ID_153","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":154,"name":"ID_154","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":155,"name":"ID_155","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":156,"name":"ID_156","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":157,"name":"ID_157","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":158,"name":"ID_158","role":"filter","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":160,"name":"ID_160","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":161,"name":"ID_161","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":162,"name":"ID_162","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":163,"name":"ID_163","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":164,"name":"ID_164","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":165,"name":"ID_165","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":166,"name":"ID_166","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":167,"name":"ID_167","role":"osc","status":"unimplemented"},{"alias_of":null,"behavior":"refuse_execution","indicator_id":168,"name":"ID_168","role":"filter","status":"unimplemented"}],"registry":"HS22_HISTORICAL_COMPLETE_V1","role_counts":{"filter":139,"level":493,"osc":372,"trend":103},"schema_version":1,"unknown_behavior":"all_nan; no_fallback","unregistered":{"MOM_JERK":"unregistered; unknown_dispatch_returns_all_nan; no_fallback"},"variant_count":1107,"variants":[{"indicator_id":0,"p1":0.0,"period":5,"role":"level"},{"indicator_id":0,"p1":0.0,"period":8,"role":"level"},{"indicator_id":0,"p1":0.0,"period":11,"role":"level"},{"indicator_id":0,"p1":0.0,"period":14,"role":"level"},{"indicator_id":0,"p1":0.0,"period":17,"role":"level"},{"indicator_id":0,"p1":0.0,"period":20,"role":"level"},{"indicator_id":0,"p1":0.0,"period":23,"role":"level"},{"indicator_id":0,"p1":0.0,"period":26,"role":"level"},{"indicator_id":0,"p1":0.0,"period":29,"role":"level"},{"indicator_id":0,"p1":0.0,"period":32,"role":"level"},{"indicator_id":0,"p1":0.0,"period":35,"role":"level"},{"indicator_id":0,"p1":0.0,"period":38,"role":"level"},{"indicator_id":0,"p1":0.0,"period":41,"role":"level"},{"indicator_id":0,"p1":0.0,"period":44,"role":"level"},{"indicator_id":0,"p1":0.0,"period":47,"role":"level"},{"indicator_id":0,"p1":0.0,"period":50,"role":"level"},{"indicator_id":1,"p1":0.0,"period":5,"role":"level"},{"indicator_id":1,"p1":0.0,"period":8,"role":"level"},{"indicator_id":1,"p1":0.0,"period":11,"role":"level"},{"indicator_id":1,"p1":0.0,"period":14,"role":"level"},{"indicator_id":1,"p1":0.0,"period":17,"role":"level"},{"indicator_id":1,"p1":0.0,"period":20,"role":"level"},{"indicator_id":1,"p1":0.0,"period":23,"role":"level"},{"indicator_id":1,"p1":0.0,"period":26,"role":"level"},{"indicator_id":1,"p1":0.0,"period":29,"role":"level"},{"indicator_id":1,"p1":0.0,"period":32,"role":"level"},{"indicator_id":1,"p1":0.0,"period":35,"role":"level"},{"indicator_id":1,"p1":0.0,"period":38,"role":"level"},{"indicator_id":1,"p1":0.0,"period":41,"role":"level"},{"indicator_id":1,"p1":0.0,"period":44,"role":"level"},{"indicator_id":1,"p1":0.0,"period":47,"role":"level"},{"indicator_id":1,"p1":0.0,"period":50,"role":"level"},{"indicator_id":2,"p1":0.0,"period":5,"role":"level"},{"indicator_id":2,"p1":0.0,"period":8,"role":"level"},{"indicator_id":2,"p1":0.0,"period":11,"role":"level"},{"indicator_id":2,"p1":0.0,"period":14,"role":"level"},{"indicator_id":2,"p1":0.0,"period":17,"role":"level"},{"indicator_id":2,"p1":0.0,"period":20,"role":"level"},{"indicator_id":2,"p1":0.0,"period":23,"role":"level"},{"indicator_id":2,"p1":0.0,"period":26,"role":"level"},{"indicator_id":2,"p1":0.0,"period":29,"role":"level"},{"indicator_id":2,"p1":0.0,"period":32,"role":"level"},{"indicator_id":2,"p1":0.0,"period":35,"role":"level"},{"indicator_id":2,"p1":0.0,"period":38,"role":"level"},{"indicator_id":2,"p1":0.0,"period":41,"role":"level"},{"indicator_id":2,"p1":0.0,"period":44,"role":"level"},{"indicator_id":2,"p1":0.0,"period":47,"role":"level"},{"indicator_id":2,"p1":0.0,"period":50,"role":"level"},{"indicator_id":3,"p1":0.0,"period":6,"role":"level"},{"indicator_id":3,"p1":0.0,"period":8,"role":"level"},{"indicator_id":3,"p1":0.0,"period":10,"role":"level"},{"indicator_id":3,"p1":0.0,"period":12,"role":"level"},{"indicator_id":3,"p1":0.0,"period":14,"role":"level"},{"indicator_id":3,"p1":0.0,"period":16,"role":"level"},{"indicator_id":3,"p1":0.0,"period":18,"role":"level"},{"indicator_id":3,"p1":0.0,"period":20,"role":"level"},{"indicator_id":3,"p1":0.0,"period":22,"role":"level"},{"indicator_id":3,"p1":0.0,"period":24,"role":"level"},{"indicator_id":3,"p1":0.0,"period":26,"role":"level"},{"indicator_id":3,"p1":0.0,"period":28,"role":"level"},{"indicator_id":3,"p1":0.0,"period":30,"role":"level"},{"indicator_id":3,"p1":0.0,"period":32,"role":"level"},{"indicator_id":3,"p1":0.0,"period":34,"role":"level"},{"indicator_id":3,"p1":0.0,"period":36,"role":"level"},{"indicator_id":3,"p1":0.0,"period":38,"role":"level"},{"indicator_id":3,"p1":0.0,"period":40,"role":"level"},{"indicator_id":3,"p1":0.0,"period":42,"role":"level"},{"indicator_id":3,"p1":0.0,"period":44,"role":"level"},{"indicator_id":3,"p1":0.0,"period":46,"role":"level"},{"indicator_id":3,"p1":0.0,"period":48,"role":"level"},{"indicator_id":3,"p1":0.0,"period":50,"role":"level"},{"indicator_id":4,"p1":0.0,"period":5,"role":"level"},{"indicator_id":4,"p1":0.0,"period":8,"role":"level"},{"indicator_id":4,"p1":0.0,"period":11,"role":"level"},{"indicator_id":4,"p1":0.0,"period":14,"role":"level"},{"indicator_id":4,"p1":0.0,"period":17,"role":"level"},{"indicator_id":4,"p1":0.0,"period":20,"role":"level"},{"indicator_id":4,"p1":0.0,"period":23,"role":"level"},{"indicator_id":4,"p1":0.0,"period":26,"role":"level"},{"indicator_id":4,"p1":0.0,"period":29,"role":"level"},{"indicator_id":4,"p1":0.0,"period":32,"role":"level"},{"indicator_id":4,"p1":0.0,"period":35,"role":"level"},{"indicator_id":4,"p1":0.0,"period":38,"role":"level"},{"indicator_id":5,"p1":0.0,"period":5,"role":"level"},{"indicator_id":5,"p1":0.0,"period":8,"role":"level"},{"indicator_id":5,"p1":0.0,"period":11,"role":"level"},{"indicator_id":5,"p1":0.0,"period":14,"role":"level"},{"indicator_id":5,"p1":0.0,"period":17,"role":"level"},{"indicator_id":5,"p1":0.0,"period":20,"role":"level"},{"indicator_id":5,"p1":0.0,"period":23,"role":"level"},{"indicator_id":5,"p1":0.0,"period":26,"role":"level"},{"indicator_id":5,"p1":0.0,"period":29,"role":"level"},{"indicator_id":5,"p1":0.0,"period":32,"role":"level"},{"indicator_id":5,"p1":0.0,"period":35,"role":"level"},{"indicator_id":6,"p1":0.0,"period":8,"role":"level"},{"indicator_id":6,"p1":0.0,"period":11,"role":"level"},{"indicator_id":6,"p1":0.0,"period":14,"role":"level"},{"indicator_id":6,"p1":0.0,"period":17,"role":"level"},{"indicator_id":6,"p1":0.0,"period":20,"role":"level"},{"indicator_id":6,"p1":0.0,"period":23,"role":"level"},{"indicator_id":6,"p1":0.0,"period":26,"role":"level"},{"indicator_id":6,"p1":0.0,"period":29,"role":"level"},{"indicator_id":6,"p1":0.0,"period":32,"role":"level"},{"indicator_id":6,"p1":0.0,"period":35,"role":"level"},{"indicator_id":7,"p1":0.0,"period":6,"role":"level"},{"indicator_id":7,"p1":0.0,"period":8,"role":"level"},{"indicator_id":7,"p1":0.0,"period":10,"role":"level"},{"indicator_id":7,"p1":0.0,"period":12,"role":"level"},{"indicator_id":7,"p1":0.0,"period":14,"role":"level"},{"indicator_id":7,"p1":0.0,"period":16,"role":"level"},{"indicator_id":7,"p1":0.0,"period":18,"role":"level"},{"indicator_id":7,"p1":0.0,"period":20,"role":"level"},{"indicator_id":7,"p1":0.0,"period":22,"role":"level"},{"indicator_id":7,"p1":0.0,"period":24,"role":"level"},{"indicator_id":7,"p1":0.0,"period":26,"role":"level"},{"indicator_id":7,"p1":0.0,"period":28,"role":"level"},{"indicator_id":7,"p1":0.0,"period":30,"role":"level"},{"indicator_id":8,"p1":0.0,"period":8,"role":"level"},{"indicator_id":8,"p1":0.0,"period":11,"role":"level"},{"indicator_id":8,"p1":0.0,"period":14,"role":"level"},{"indicator_id":8,"p1":0.0,"period":17,"role":"level"},{"indicator_id":8,"p1":0.0,"period":20,"role":"level"},{"indicator_id":8,"p1":0.0,"period":23,"role":"level"},{"indicator_id":8,"p1":0.0,"period":26,"role":"level"},{"indicator_id":8,"p1":0.0,"period":29,"role":"level"},{"indicator_id":8,"p1":0.0,"period":32,"role":"level"},{"indicator_id":8,"p1":0.0,"period":35,"role":"level"},{"indicator_id":9,"p1":-50.0,"period":8,"role":"level"},{"indicator_id":9,"p1":0.0,"period":8,"role":"level"},{"indicator_id":9,"p1":50.0,"period":8,"role":"level"},{"indicator_id":9,"p1":100.0,"period":8,"role":"level"},{"indicator_id":9,"p1":-50.0,"period":12,"role":"level"},{"indicator_id":9,"p1":0.0,"period":12,"role":"level"},{"indicator_id":9,"p1":50.0,"period":12,"role":"level"},{"indicator_id":9,"p1":100.0,"period":12,"role":"level"},{"indicator_id":9,"p1":-50.0,"period":16,"role":"level"},{"indicator_id":9,"p1":0.0,"period":16,"role":"level"},{"indicator_id":9,"p1":50.0,"period":16,"role":"level"},{"indicator_id":9,"p1":100.0,"period":16,"role":"level"},{"indicator_id":9,"p1":-50.0,"period":20,"role":"level"},{"indicator_id":9,"p1":0.0,"period":20,"role":"level"},{"indicator_id":9,"p1":50.0,"period":20,"role":"level"},{"indicator_id":9,"p1":100.0,"period":20,"role":"level"},{"indicator_id":9,"p1":-50.0,"period":24,"role":"level"},{"indicator_id":9,"p1":0.0,"period":24,"role":"level"},{"indicator_id":9,"p1":50.0,"period":24,"role":"level"},{"indicator_id":9,"p1":100.0,"period":24,"role":"level"},{"indicator_id":9,"p1":-50.0,"period":28,"role":"level"},{"indicator_id":9,"p1":0.0,"period":28,"role":"level"},{"indicator_id":9,"p1":50.0,"period":28,"role":"level"},{"indicator_id":9,"p1":100.0,"period":28,"role":"level"},{"indicator_id":9,"p1":-50.0,"period":32,"role":"level"},{"indicator_id":9,"p1":0.0,"period":32,"role":"level"},{"indicator_id":9,"p1":50.0,"period":32,"role":"level"},{"indicator_id":9,"p1":100.0,"period":32,"role":"level"},{"indicator_id":10,"p1":0.6,"period":8,"role":"level"},{"indicator_id":10,"p1":0.7,"period":8,"role":"level"},{"indicator_id":10,"p1":0.8,"period":8,"role":"level"},{"indicator_id":10,"p1":0.9,"period":8,"role":"level"},{"indicator_id":10,"p1":0.6,"period":11,"role":"level"},{"indicator_id":10,"p1":0.7,"period":11,"role":"level"},{"indicator_id":10,"p1":0.8,"period":11,"role":"level"},{"indicator_id":10,"p1":0.9,"period":11,"role":"level"},{"indicator_id":10,"p1":0.6,"period":14,"role":"level"},{"indicator_id":10,"p1":0.7,"period":14,"role":"level"},{"indicator_id":10,"p1":0.8,"period":14,"role":"level"},{"indicator_id":10,"p1":0.9,"period":14,"role":"level"},{"indicator_id":10,"p1":0.6,"period":17,"role":"level"},{"indicator_id":10,"p1":0.7,"period":17,"role":"level"},{"indicator_id":10,"p1":0.8,"period":17,"role":"level"},{"indicator_id":10,"p1":0.9,"period":17,"role":"level"},{"indicator_id":10,"p1":0.6,"period":20,"role":"level"},{"indicator_id":10,"p1":0.7,"period":20,"role":"level"},{"indicator_id":10,"p1":0.8,"period":20,"role":"level"},{"indicator_id":10,"p1":0.9,"period":20,"role":"level"},{"indicator_id":10,"p1":0.6,"period":23,"role":"level"},{"indicator_id":10,"p1":0.7,"period":23,"role":"level"},{"indicator_id":10,"p1":0.8,"period":23,"role":"level"},{"indicator_id":10,"p1":0.9,"period":23,"role":"level"},{"indicator_id":10,"p1":0.6,"period":26,"role":"level"},{"indicator_id":10,"p1":0.7,"period":26,"role":"level"},{"indicator_id":10,"p1":0.8,"period":26,"role":"level"},{"indicator_id":10,"p1":0.9,"period":26,"role":"level"},{"indicator_id":10,"p1":0.6,"period":29,"role":"level"},{"indicator_id":10,"p1":0.7,"period":29,"role":"level"},{"indicator_id":10,"p1":0.8,"period":29,"role":"level"},{"indicator_id":10,"p1":0.9,"period":29,"role":"level"},{"indicator_id":11,"p1":4.0,"period":8,"role":"level"},{"indicator_id":11,"p1":6.0,"period":8,"role":"level"},{"indicator_id":11,"p1":8.0,"period":8,"role":"level"},{"indicator_id":11,"p1":4.0,"period":11,"role":"level"},{"indicator_id":11,"p1":6.0,"period":11,"role":"level"},{"indicator_id":11,"p1":8.0,"period":11,"role":"level"},{"indicator_id":11,"p1":4.0,"period":14,"role":"level"},{"indicator_id":11,"p1":6.0,"period":14,"role":"level"},{"indicator_id":11,"p1":8.0,"period":14,"role":"level"},{"indicator_id":11,"p1":4.0,"period":17,"role":"level"},{"indicator_id":11,"p1":6.0,"period":17,"role":"level"},{"indicator_id":11,"p1":8.0,"period":17,"role":"level"},{"indicator_id":11,"p1":4.0,"period":20,"role":"level"},{"indicator_id":11,"p1":6.0,"period":20,"role":"level"},{"indicator_id":11,"p1":8.0,"period":20,"role":"level"},{"indicator_id":11,"p1":4.0,"period":23,"role":"level"},{"indicator_id":11,"p1":6.0,"period":23,"role":"level"},{"indicator_id":11,"p1":8.0,"period":23,"role":"level"},{"indicator_id":11,"p1":4.0,"period":26,"role":"level"},{"indicator_id":11,"p1":6.0,"period":26,"role":"level"},{"indicator_id":11,"p1":8.0,"period":26,"role":"level"},{"indicator_id":11,"p1":4.0,"period":29,"role":"level"},{"indicator_id":11,"p1":6.0,"period":29,"role":"level"},{"indicator_id":11,"p1":8.0,"period":29,"role":"level"},{"indicator_id":12,"p1":0.0,"period":5,"role":"level"},{"indicator_id":12,"p1":0.0,"period":8,"role":"level"},{"indicator_id":12,"p1":0.0,"period":11,"role":"level"},{"indicator_id":12,"p1":0.0,"period":14,"role":"level"},{"indicator_id":12,"p1":0.0,"period":17,"role":"level"},{"indicator_id":12,"p1":0.0,"period":20,"role":"level"},{"indicator_id":12,"p1":0.0,"period":23,"role":"level"},{"indicator_id":12,"p1":0.0,"period":26,"role":"level"},{"indicator_id":12,"p1":0.0,"period":29,"role":"level"},{"indicator_id":12,"p1":0.0,"period":32,"role":"level"},{"indicator_id":12,"p1":0.0,"period":35,"role":"level"},{"indicator_id":12,"p1":0.0,"period":38,"role":"level"},{"indicator_id":13,"p1":0.0,"period":8,"role":"level"},{"indicator_id":13,"p1":0.0,"period":12,"role":"level"},{"indicator_id":13,"p1":0.0,"period":16,"role":"level"},{"indicator_id":13,"p1":0.0,"period":20,"role":"level"},{"indicator_id":13,"p1":0.0,"period":24,"role":"level"},{"indicator_id":13,"p1":0.0,"period":28,"role":"level"},{"indicator_id":13,"p1":0.0,"period":32,"role":"level"},{"indicator_id":14,"p1":0.0,"period":10,"role":"level"},{"indicator_id":14,"p1":0.0,"period":14,"role":"level"},{"indicator_id":14,"p1":0.0,"period":18,"role":"level"},{"indicator_id":14,"p1":0.0,"period":22,"role":"level"},{"indicator_id":14,"p1":0.0,"period":26,"role":"level"},{"indicator_id":14,"p1":0.0,"period":30,"role":"level"},{"indicator_id":14,"p1":0.0,"period":34,"role":"level"},{"indicator_id":14,"p1":0.0,"period":38,"role":"level"},{"indicator_id":15,"p1":0.0,"period":8,"role":"level"},{"indicator_id":15,"p1":0.0,"period":11,"role":"level"},{"indicator_id":15,"p1":0.0,"period":14,"role":"level"},{"indicator_id":15,"p1":0.0,"period":17,"role":"level"},{"indicator_id":15,"p1":0.0,"period":20,"role":"level"},{"indicator_id":15,"p1":0.0,"period":23,"role":"level"},{"indicator_id":15,"p1":0.0,"period":26,"role":"level"},{"indicator_id":15,"p1":0.0,"period":29,"role":"level"},{"indicator_id":15,"p1":0.0,"period":32,"role":"level"},{"indicator_id":15,"p1":0.0,"period":35,"role":"level"},{"indicator_id":15,"p1":0.0,"period":38,"role":"level"},{"indicator_id":16,"p1":0.0,"period":5,"role":"level"},{"indicator_id":16,"p1":0.0,"period":8,"role":"level"},{"indicator_id":16,"p1":0.0,"period":11,"role":"level"},{"indicator_id":16,"p1":0.0,"period":14,"role":"level"},{"indicator_id":16,"p1":0.0,"period":17,"role":"level"},{"indicator_id":16,"p1":0.0,"period":20,"role":"level"},{"indicator_id":16,"p1":0.0,"period":23,"role":"level"},{"indicator_id":16,"p1":0.0,"period":26,"role":"level"},{"indicator_id":16,"p1":0.0,"period":29,"role":"level"},{"indicator_id":17,"p1":1.5,"period":14,"role":"level"},{"indicator_id":17,"p1":2.0,"period":14,"role":"level"},{"indicator_id":17,"p1":2.5,"period":14,"role":"level"},{"indicator_id":17,"p1":1.5,"period":16,"role":"level"},{"indicator_id":17,"p1":2.0,"period":16,"role":"level"},{"indicator_id":17,"p1":2.5,"period":16,"role":"level"},{"indicator_id":17,"p1":1.5,"period":18,"role":"level"},{"indicator_id":17,"p1":2.0,"period":18,"role":"level"},{"indicator_id":17,"p1":2.5,"period":18,"role":"level"},{"indicator_id":17,"p1":1.5,"period":20,"role":"level"},{"indicator_id":17,"p1":2.0,"period":20,"role":"level"},{"indicator_id":17,"p1":2.5,"period":20,"role":"level"},{"indicator_id":17,"p1":1.5,"period":22,"role":"level"},{"indicator_id":17,"p1":2.0,"period":22,"role":"level"},{"indicator_id":17,"p1":2.5,"period":22,"role":"level"},{"indicator_id":17,"p1":1.5,"period":24,"role":"level"},{"indicator_id":17,"p1":2.0,"period":24,"role":"level"},{"indicator_id":17,"p1":2.5,"period":24,"role":"level"},{"indicator_id":18,"p1":1.5,"period":14,"role":"level"},{"indicator_id":18,"p1":2.0,"period":14,"role":"level"},{"indicator_id":18,"p1":2.5,"period":14,"role":"level"},{"indicator_id":18,"p1":1.5,"period":16,"role":"level"},{"indicator_id":18,"p1":2.0,"period":16,"role":"level"},{"indicator_id":18,"p1":2.5,"period":16,"role":"level"},{"indicator_id":18,"p1":1.5,"period":18,"role":"level"},{"indicator_id":18,"p1":2.0,"period":18,"role":"level"},{"indicator_id":18,"p1":2.5,"period":18,"role":"level"},{"indicator_id":18,"p1":1.5,"period":20,"role":"level"},{"indicator_id":18,"p1":2.0,"period":20,"role":"level"},{"indicator_id":18,"p1":2.5,"period":20,"role":"level"},{"indicator_id":18,"p1":1.5,"period":22,"role":"level"},{"indicator_id":18,"p1":2.0,"period":22,"role":"level"},{"indicator_id":18,"p1":2.5,"period":22,"role":"level"},{"indicator_id":18,"p1":1.5,"period":24,"role":"level"},{"indicator_id":18,"p1":2.0,"period":24,"role":"level"},{"indicator_id":18,"p1":2.5,"period":24,"role":"level"},{"indicator_id":19,"p1":2.0,"period":8,"role":"level"},{"indicator_id":19,"p1":3.0,"period":8,"role":"level"},{"indicator_id":19,"p1":4.0,"period":8,"role":"level"},{"indicator_id":19,"p1":2.0,"period":10,"role":"level"},{"indicator_id":19,"p1":3.0,"period":10,"role":"level"},{"indicator_id":19,"p1":4.0,"period":10,"role":"level"},{"indicator_id":19,"p1":2.0,"period":12,"role":"level"},{"indicator_id":19,"p1":3.0,"period":12,"role":"level"},{"indicator_id":19,"p1":4.0,"period":12,"role":"level"},{"indicator_id":19,"p1":2.0,"period":14,"role":"level"},{"indicator_id":19,"p1":3.0,"period":14,"role":"level"},{"indicator_id":19,"p1":4.0,"period":14,"role":"level"},{"indicator_id":20,"p1":0.0,"period":10,"role":"level"},{"indicator_id":20,"p1":0.0,"period":14,"role":"level"},{"indicator_id":20,"p1":0.0,"period":18,"role":"level"},{"indicator_id":20,"p1":0.0,"period":22,"role":"level"},{"indicator_id":20,"p1":0.0,"period":26,"role":"level"},{"indicator_id":21,"p1":0.0,"period":10,"role":"level"},{"indicator_id":21,"p1":0.0,"period":14,"role":"level"},{"indicator_id":21,"p1":0.0,"period":18,"role":"level"},{"indicator_id":21,"p1":0.0,"period":22,"role":"level"},{"indicator_id":21,"p1":0.0,"period":26,"role":"level"},{"indicator_id":22,"p1":0.0,"period":10,"role":"level"},{"indicator_id":22,"p1":0.0,"period":14,"role":"level"},{"indicator_id":22,"p1":0.0,"period":18,"role":"level"},{"indicator_id":22,"p1":0.0,"period":22,"role":"level"},{"indicator_id":22,"p1":0.0,"period":26,"role":"level"},{"indicator_id":23,"p1":1.0,"period":14,"role":"level"},{"indicator_id":23,"p1":1.5,"period":14,"role":"level"},{"indicator_id":23,"p1":2.0,"period":14,"role":"level"},{"indicator_id":23,"p1":1.0,"period":16,"role":"level"},{"indicator_id":23,"p1":1.5,"period":16,"role":"level"},{"indicator_id":23,"p1":2.0,"period":16,"role":"level"},{"indicator_id":23,"p1":1.0,"period":18,"role":"level"},{"indicator_id":23,"p1":1.5,"period":18,"role":"level"},{"indicator_id":23,"p1":2.0,"period":18,"role":"level"},{"indicator_id":23,"p1":1.0,"period":20,"role":"level"},{"indicator_id":23,"p1":1.5,"period":20,"role":"level"},{"indicator_id":23,"p1":2.0,"period":20,"role":"level"},{"indicator_id":23,"p1":1.0,"period":22,"role":"level"},{"indicator_id":23,"p1":1.5,"period":22,"role":"level"},{"indicator_id":23,"p1":2.0,"period":22,"role":"level"},{"indicator_id":23,"p1":1.0,"period":24,"role":"level"},{"indicator_id":23,"p1":1.5,"period":24,"role":"level"},{"indicator_id":23,"p1":2.0,"period":24,"role":"level"},{"indicator_id":24,"p1":1.0,"period":14,"role":"level"},{"indicator_id":24,"p1":1.5,"period":14,"role":"level"},{"indicator_id":24,"p1":2.0,"period":14,"role":"level"},{"indicator_id":24,"p1":1.0,"period":16,"role":"level"},{"indicator_id":24,"p1":1.5,"period":16,"role":"level"},{"indicator_id":24,"p1":2.0,"period":16,"role":"level"},{"indicator_id":24,"p1":1.0,"period":18,"role":"level"},{"indicator_id":24,"p1":1.5,"period":18,"role":"level"},{"indicator_id":24,"p1":2.0,"period":18,"role":"level"},{"indicator_id":24,"p1":1.0,"period":20,"role":"level"},{"indicator_id":24,"p1":1.5,"period":20,"role":"level"},{"indicator_id":24,"p1":2.0,"period":20,"role":"level"},{"indicator_id":24,"p1":1.0,"period":22,"role":"level"},{"indicator_id":24,"p1":1.5,"period":22,"role":"level"},{"indicator_id":24,"p1":2.0,"period":22,"role":"level"},{"indicator_id":24,"p1":1.0,"period":24,"role":"level"},{"indicator_id":24,"p1":1.5,"period":24,"role":"level"},{"indicator_id":24,"p1":2.0,"period":24,"role":"level"},{"indicator_id":25,"p1":0.0,"period":14,"role":"level"},{"indicator_id":25,"p1":0.0,"period":16,"role":"level"},{"indicator_id":25,"p1":0.0,"period":18,"role":"level"},{"indicator_id":25,"p1":0.0,"period":20,"role":"level"},{"indicator_id":25,"p1":0.0,"period":22,"role":"level"},{"indicator_id":25,"p1":0.0,"period":24,"role":"level"},{"indicator_id":26,"p1":0.0,"period":7,"role":"level"},{"indicator_id":26,"p1":0.0,"period":9,"role":"level"},{"indicator_id":26,"p1":0.0,"period":11,"role":"level"},{"indicator_id":27,"p1":0.0,"period":20,"role":"level"},{"indicator_id":27,"p1":0.0,"period":22,"role":"level"},{"indicator_id":27,"p1":0.0,"period":24,"role":"level"},{"indicator_id":27,"p1":0.0,"period":26,"role":"level"},{"indicator_id":27,"p1":0.0,"period":28,"role":"level"},{"indicator_id":28,"p1":0.01,"period":1,"role":"level"},{"indicator_id":28,"p1":0.02,"period":1,"role":"level"},{"indicator_id":28,"p1":0.03,"period":1,"role":"level"},{"indicator_id":30,"p1":0.0,"period":6,"role":"osc"},{"indicator_id":30,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":30,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":30,"p1":0.0,"period":12,"role":"osc"},{"indicator_id":30,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":30,"p1":0.0,"period":16,"role":"osc"},{"indicator_id":30,"p1":0.0,"period":18,"role":"osc"},{"indicator_id":30,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":30,"p1":0.0,"period":22,"role":"osc"},{"indicator_id":30,"p1":0.0,"period":24,"role":"osc"},{"indicator_id":30,"p1":0.0,"period":26,"role":"osc"},{"indicator_id":31,"p1":0.0,"period":5,"role":"osc"},{"indicator_id":31,"p1":0.0,"period":7,"role":"osc"},{"indicator_id":31,"p1":0.0,"period":9,"role":"osc"},{"indicator_id":31,"p1":0.0,"period":11,"role":"osc"},{"indicator_id":31,"p1":0.0,"period":13,"role":"osc"},{"indicator_id":31,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":31,"p1":0.0,"period":17,"role":"osc"},{"indicator_id":31,"p1":0.0,"period":19,"role":"osc"},{"indicator_id":31,"p1":0.0,"period":21,"role":"osc"},{"indicator_id":32,"p1":0.0,"period":5,"role":"osc"},{"indicator_id":32,"p1":0.0,"period":7,"role":"osc"},{"indicator_id":32,"p1":0.0,"period":9,"role":"osc"},{"indicator_id":32,"p1":0.0,"period":11,"role":"osc"},{"indicator_id":32,"p1":0.0,"period":13,"role":"osc"},{"indicator_id":32,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":32,"p1":0.0,"period":17,"role":"osc"},{"indicator_id":32,"p1":0.0,"period":19,"role":"osc"},{"indicator_id":32,"p1":0.0,"period":21,"role":"osc"},{"indicator_id":33,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":33,"p1":0.0,"period":12,"role":"osc"},{"indicator_id":33,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":33,"p1":0.0,"period":16,"role":"osc"},{"indicator_id":33,"p1":0.0,"period":18,"role":"osc"},{"indicator_id":33,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":33,"p1":0.0,"period":22,"role":"osc"},{"indicator_id":33,"p1":0.0,"period":24,"role":"osc"},{"indicator_id":33,"p1":0.0,"period":26,"role":"osc"},{"indicator_id":33,"p1":0.0,"period":28,"role":"osc"},{"indicator_id":34,"p1":0.0,"period":5,"role":"osc"},{"indicator_id":34,"p1":0.0,"period":7,"role":"osc"},{"indicator_id":34,"p1":0.0,"period":9,"role":"osc"},{"indicator_id":34,"p1":0.0,"period":11,"role":"osc"},{"indicator_id":34,"p1":0.0,"period":13,"role":"osc"},{"indicator_id":34,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":34,"p1":0.0,"period":17,"role":"osc"},{"indicator_id":34,"p1":0.0,"period":19,"role":"osc"},{"indicator_id":34,"p1":0.0,"period":21,"role":"osc"},{"indicator_id":35,"p1":0.0,"period":5,"role":"osc"},{"indicator_id":35,"p1":0.0,"period":7,"role":"osc"},{"indicator_id":35,"p1":0.0,"period":9,"role":"osc"},{"indicator_id":35,"p1":0.0,"period":11,"role":"osc"},{"indicator_id":35,"p1":0.0,"period":13,"role":"osc"},{"indicator_id":35,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":35,"p1":0.0,"period":17,"role":"osc"},{"indicator_id":35,"p1":0.0,"period":19,"role":"osc"},{"indicator_id":36,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":36,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":36,"p1":0.0,"period":12,"role":"osc"},{"indicator_id":36,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":36,"p1":0.0,"period":16,"role":"osc"},{"indicator_id":36,"p1":0.0,"period":18,"role":"osc"},{"indicator_id":36,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":37,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":37,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":37,"p1":0.0,"period":12,"role":"osc"},{"indicator_id":37,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":37,"p1":0.0,"period":16,"role":"osc"},{"indicator_id":37,"p1":0.0,"period":18,"role":"osc"},{"indicator_id":37,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":38,"p1":0.0,"period":16,"role":"osc"},{"indicator_id":38,"p1":0.0,"period":18,"role":"osc"},{"indicator_id":38,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":38,"p1":0.0,"period":22,"role":"osc"},{"indicator_id":38,"p1":0.0,"period":24,"role":"osc"},{"indicator_id":38,"p1":0.0,"period":26,"role":"osc"},{"indicator_id":38,"p1":0.0,"period":28,"role":"osc"},{"indicator_id":39,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":39,"p1":0.0,"period":22,"role":"osc"},{"indicator_id":39,"p1":0.0,"period":24,"role":"osc"},{"indicator_id":39,"p1":0.0,"period":26,"role":"osc"},{"indicator_id":39,"p1":0.0,"period":28,"role":"osc"},{"indicator_id":39,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":40,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":40,"p1":0.0,"period":12,"role":"osc"},{"indicator_id":40,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":40,"p1":0.0,"period":16,"role":"osc"},{"indicator_id":40,"p1":0.0,"period":18,"role":"osc"},{"indicator_id":40,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":41,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":41,"p1":0.0,"period":12,"role":"osc"},{"indicator_id":41,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":41,"p1":0.0,"period":16,"role":"osc"},{"indicator_id":41,"p1":0.0,"period":18,"role":"osc"},{"indicator_id":41,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":41,"p1":0.0,"period":22,"role":"osc"},{"indicator_id":41,"p1":0.0,"period":24,"role":"osc"},{"indicator_id":42,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":42,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":42,"p1":0.0,"period":26,"role":"osc"},{"indicator_id":42,"p1":0.0,"period":32,"role":"osc"},{"indicator_id":42,"p1":0.0,"period":38,"role":"osc"},{"indicator_id":42,"p1":0.0,"period":44,"role":"osc"},{"indicator_id":42,"p1":0.0,"period":50,"role":"osc"},{"indicator_id":43,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":43,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":43,"p1":0.0,"period":26,"role":"osc"},{"indicator_id":43,"p1":0.0,"period":32,"role":"osc"},{"indicator_id":43,"p1":0.0,"period":38,"role":"osc"},{"indicator_id":43,"p1":0.0,"period":44,"role":"osc"},{"indicator_id":43,"p1":0.0,"period":50,"role":"osc"},{"indicator_id":44,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":44,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":44,"p1":0.0,"period":26,"role":"osc"},{"indicator_id":44,"p1":0.0,"period":32,"role":"osc"},{"indicator_id":44,"p1":0.0,"period":38,"role":"osc"},{"indicator_id":44,"p1":0.0,"period":44,"role":"osc"},{"indicator_id":44,"p1":0.0,"period":50,"role":"osc"},{"indicator_id":90,"p1":0.0,"period":5,"role":"osc"},{"indicator_id":90,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":90,"p1":0.0,"period":11,"role":"osc"},{"indicator_id":90,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":90,"p1":0.0,"period":17,"role":"osc"},{"indicator_id":90,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":91,"p1":0.0,"period":5,"role":"osc"},{"indicator_id":91,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":91,"p1":0.0,"period":11,"role":"osc"},{"indicator_id":91,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":91,"p1":0.0,"period":17,"role":"osc"},{"indicator_id":91,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":92,"p1":0.0,"period":5,"role":"osc"},{"indicator_id":92,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":92,"p1":0.0,"period":11,"role":"osc"},{"indicator_id":92,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":92,"p1":0.0,"period":17,"role":"osc"},{"indicator_id":92,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":93,"p1":0.0,"period":5,"role":"osc"},{"indicator_id":93,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":93,"p1":0.0,"period":11,"role":"osc"},{"indicator_id":93,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":93,"p1":0.0,"period":17,"role":"osc"},{"indicator_id":93,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":94,"p1":0.0,"period":5,"role":"osc"},{"indicator_id":94,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":94,"p1":0.0,"period":11,"role":"osc"},{"indicator_id":94,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":94,"p1":0.0,"period":17,"role":"osc"},{"indicator_id":94,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":95,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":95,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":95,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":96,"p1":0.0,"period":1,"role":"osc"},{"indicator_id":97,"p1":0.0,"period":5,"role":"osc"},{"indicator_id":97,"p1":0.0,"period":9,"role":"osc"},{"indicator_id":97,"p1":0.0,"period":13,"role":"osc"},{"indicator_id":97,"p1":0.0,"period":17,"role":"osc"},{"indicator_id":98,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":98,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":98,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":98,"p1":0.0,"period":25,"role":"osc"},{"indicator_id":98,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":99,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":99,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":99,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":99,"p1":0.0,"period":25,"role":"osc"},{"indicator_id":99,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":100,"p1":0.0,"period":5,"role":"osc"},{"indicator_id":100,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":100,"p1":0.0,"period":11,"role":"osc"},{"indicator_id":100,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":100,"p1":0.0,"period":17,"role":"osc"},{"indicator_id":100,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":101,"p1":0.0,"period":5,"role":"osc"},{"indicator_id":101,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":101,"p1":0.0,"period":11,"role":"osc"},{"indicator_id":101,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":101,"p1":0.0,"period":17,"role":"osc"},{"indicator_id":101,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":102,"p1":0.0,"period":12,"role":"osc"},{"indicator_id":102,"p1":0.0,"period":16,"role":"osc"},{"indicator_id":102,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":102,"p1":0.0,"period":24,"role":"osc"},{"indicator_id":102,"p1":0.0,"period":28,"role":"osc"},{"indicator_id":103,"p1":0.0,"period":5,"role":"osc"},{"indicator_id":103,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":103,"p1":0.0,"period":11,"role":"osc"},{"indicator_id":103,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":103,"p1":0.0,"period":17,"role":"osc"},{"indicator_id":103,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":104,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":104,"p1":0.0,"period":11,"role":"osc"},{"indicator_id":104,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":104,"p1":0.0,"period":17,"role":"osc"},{"indicator_id":104,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":104,"p1":0.0,"period":23,"role":"osc"},{"indicator_id":104,"p1":0.0,"period":26,"role":"osc"},{"indicator_id":104,"p1":0.0,"period":29,"role":"osc"},{"indicator_id":105,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":105,"p1":0.0,"period":18,"role":"osc"},{"indicator_id":105,"p1":0.0,"period":22,"role":"osc"},{"indicator_id":105,"p1":0.0,"period":26,"role":"osc"},{"indicator_id":105,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":105,"p1":0.0,"period":34,"role":"osc"},{"indicator_id":105,"p1":0.0,"period":38,"role":"osc"},{"indicator_id":106,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":106,"p1":0.0,"period":11,"role":"osc"},{"indicator_id":106,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":106,"p1":0.0,"period":17,"role":"osc"},{"indicator_id":106,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":107,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":107,"p1":0.0,"period":11,"role":"osc"},{"indicator_id":107,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":107,"p1":0.0,"period":17,"role":"osc"},{"indicator_id":107,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":108,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":108,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":108,"p1":0.0,"period":26,"role":"osc"},{"indicator_id":108,"p1":0.0,"period":32,"role":"osc"},{"indicator_id":108,"p1":0.0,"period":38,"role":"osc"},{"indicator_id":108,"p1":0.0,"period":44,"role":"osc"},{"indicator_id":108,"p1":0.0,"period":50,"role":"osc"},{"indicator_id":109,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":109,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":109,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":109,"p1":0.0,"period":40,"role":"osc"},{"indicator_id":109,"p1":0.0,"period":50,"role":"osc"},{"indicator_id":110,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":110,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":110,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":110,"p1":0.0,"period":40,"role":"osc"},{"indicator_id":110,"p1":0.0,"period":50,"role":"osc"},{"indicator_id":116,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":116,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":116,"p1":0.0,"period":40,"role":"osc"},{"indicator_id":116,"p1":0.0,"period":50,"role":"osc"},{"indicator_id":116,"p1":0.0,"period":60,"role":"osc"},{"indicator_id":52,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":52,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":52,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":52,"p1":0.0,"period":25,"role":"osc"},{"indicator_id":52,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":59,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":59,"p1":0.0,"period":18,"role":"osc"},{"indicator_id":59,"p1":0.0,"period":22,"role":"osc"},{"indicator_id":59,"p1":0.0,"period":26,"role":"osc"},{"indicator_id":59,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":60,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":60,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":60,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":60,"p1":0.0,"period":25,"role":"osc"},{"indicator_id":60,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":70,"p1":0.0,"period":10,"role":"trend"},{"indicator_id":70,"p1":0.0,"period":12,"role":"trend"},{"indicator_id":70,"p1":0.0,"period":14,"role":"trend"},{"indicator_id":70,"p1":0.0,"period":16,"role":"trend"},{"indicator_id":70,"p1":0.0,"period":18,"role":"trend"},{"indicator_id":70,"p1":0.0,"period":20,"role":"trend"},{"indicator_id":71,"p1":0.0,"period":10,"role":"trend"},{"indicator_id":71,"p1":0.0,"period":14,"role":"trend"},{"indicator_id":71,"p1":0.0,"period":18,"role":"trend"},{"indicator_id":71,"p1":0.0,"period":22,"role":"trend"},{"indicator_id":71,"p1":0.0,"period":26,"role":"trend"},{"indicator_id":72,"p1":0.0,"period":10,"role":"trend"},{"indicator_id":72,"p1":0.0,"period":14,"role":"trend"},{"indicator_id":72,"p1":0.0,"period":18,"role":"trend"},{"indicator_id":72,"p1":0.0,"period":22,"role":"trend"},{"indicator_id":72,"p1":0.0,"period":26,"role":"trend"},{"indicator_id":73,"p1":0.0,"period":8,"role":"trend"},{"indicator_id":73,"p1":0.0,"period":11,"role":"trend"},{"indicator_id":73,"p1":0.0,"period":14,"role":"trend"},{"indicator_id":73,"p1":0.0,"period":17,"role":"trend"},{"indicator_id":73,"p1":0.0,"period":20,"role":"trend"},{"indicator_id":73,"p1":0.0,"period":23,"role":"trend"},{"indicator_id":73,"p1":0.0,"period":26,"role":"trend"},{"indicator_id":73,"p1":0.0,"period":29,"role":"trend"},{"indicator_id":74,"p1":0.0,"period":8,"role":"trend"},{"indicator_id":74,"p1":0.0,"period":11,"role":"trend"},{"indicator_id":74,"p1":0.0,"period":14,"role":"trend"},{"indicator_id":74,"p1":0.0,"period":17,"role":"trend"},{"indicator_id":74,"p1":0.0,"period":20,"role":"trend"},{"indicator_id":74,"p1":0.0,"period":23,"role":"trend"},{"indicator_id":74,"p1":0.0,"period":26,"role":"trend"},{"indicator_id":74,"p1":0.0,"period":29,"role":"trend"},{"indicator_id":75,"p1":0.0,"period":8,"role":"trend"},{"indicator_id":75,"p1":0.0,"period":11,"role":"trend"},{"indicator_id":75,"p1":0.0,"period":14,"role":"trend"},{"indicator_id":75,"p1":0.0,"period":17,"role":"trend"},{"indicator_id":75,"p1":0.0,"period":20,"role":"trend"},{"indicator_id":75,"p1":0.0,"period":23,"role":"trend"},{"indicator_id":75,"p1":0.0,"period":26,"role":"trend"},{"indicator_id":75,"p1":0.0,"period":29,"role":"trend"},{"indicator_id":76,"p1":0.0,"period":8,"role":"trend"},{"indicator_id":76,"p1":0.0,"period":11,"role":"trend"},{"indicator_id":76,"p1":0.0,"period":14,"role":"trend"},{"indicator_id":76,"p1":0.0,"period":17,"role":"trend"},{"indicator_id":76,"p1":0.0,"period":20,"role":"trend"},{"indicator_id":76,"p1":0.0,"period":23,"role":"trend"},{"indicator_id":76,"p1":0.0,"period":26,"role":"trend"},{"indicator_id":76,"p1":0.0,"period":29,"role":"trend"},{"indicator_id":77,"p1":0.0,"period":1,"role":"trend"},{"indicator_id":78,"p1":0.0,"period":20,"role":"trend"},{"indicator_id":78,"p1":0.0,"period":30,"role":"trend"},{"indicator_id":78,"p1":0.0,"period":40,"role":"trend"},{"indicator_id":78,"p1":0.0,"period":50,"role":"trend"},{"indicator_id":78,"p1":0.0,"period":60,"role":"trend"},{"indicator_id":80,"p1":0.0,"period":20,"role":"trend"},{"indicator_id":80,"p1":0.0,"period":30,"role":"trend"},{"indicator_id":80,"p1":0.0,"period":40,"role":"trend"},{"indicator_id":80,"p1":0.0,"period":50,"role":"trend"},{"indicator_id":80,"p1":0.0,"period":60,"role":"trend"},{"indicator_id":81,"p1":0.0,"period":10,"role":"trend"},{"indicator_id":81,"p1":0.0,"period":15,"role":"trend"},{"indicator_id":81,"p1":0.0,"period":20,"role":"trend"},{"indicator_id":81,"p1":0.0,"period":25,"role":"trend"},{"indicator_id":81,"p1":0.0,"period":30,"role":"trend"},{"indicator_id":83,"p1":0.0,"period":5,"role":"trend"},{"indicator_id":83,"p1":0.0,"period":8,"role":"trend"},{"indicator_id":83,"p1":0.0,"period":11,"role":"trend"},{"indicator_id":83,"p1":0.0,"period":14,"role":"trend"},{"indicator_id":83,"p1":0.0,"period":17,"role":"trend"},{"indicator_id":83,"p1":0.0,"period":20,"role":"trend"},{"indicator_id":79,"p1":2.0,"period":20,"role":"trend"},{"indicator_id":79,"p1":4.0,"period":20,"role":"trend"},{"indicator_id":79,"p1":8.0,"period":20,"role":"trend"},{"indicator_id":79,"p1":2.0,"period":30,"role":"trend"},{"indicator_id":79,"p1":4.0,"period":30,"role":"trend"},{"indicator_id":79,"p1":8.0,"period":30,"role":"trend"},{"indicator_id":79,"p1":2.0,"period":40,"role":"trend"},{"indicator_id":79,"p1":4.0,"period":40,"role":"trend"},{"indicator_id":79,"p1":8.0,"period":40,"role":"trend"},{"indicator_id":79,"p1":2.0,"period":50,"role":"trend"},{"indicator_id":79,"p1":4.0,"period":50,"role":"trend"},{"indicator_id":79,"p1":8.0,"period":50,"role":"trend"},{"indicator_id":79,"p1":2.0,"period":60,"role":"trend"},{"indicator_id":79,"p1":4.0,"period":60,"role":"trend"},{"indicator_id":79,"p1":8.0,"period":60,"role":"trend"},{"indicator_id":82,"p1":1.0,"period":20,"role":"trend"},{"indicator_id":82,"p1":3.0,"period":20,"role":"trend"},{"indicator_id":82,"p1":5.0,"period":20,"role":"trend"},{"indicator_id":82,"p1":1.0,"period":30,"role":"trend"},{"indicator_id":82,"p1":3.0,"period":30,"role":"trend"},{"indicator_id":82,"p1":5.0,"period":30,"role":"trend"},{"indicator_id":82,"p1":1.0,"period":40,"role":"trend"},{"indicator_id":82,"p1":3.0,"period":40,"role":"trend"},{"indicator_id":82,"p1":5.0,"period":40,"role":"trend"},{"indicator_id":82,"p1":1.0,"period":50,"role":"trend"},{"indicator_id":82,"p1":3.0,"period":50,"role":"trend"},{"indicator_id":82,"p1":5.0,"period":50,"role":"trend"},{"indicator_id":50,"p1":0.0,"period":8,"role":"filter"},{"indicator_id":50,"p1":0.0,"period":10,"role":"filter"},{"indicator_id":50,"p1":0.0,"period":12,"role":"filter"},{"indicator_id":50,"p1":0.0,"period":14,"role":"filter"},{"indicator_id":50,"p1":0.0,"period":16,"role":"filter"},{"indicator_id":50,"p1":0.0,"period":18,"role":"filter"},{"indicator_id":50,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":51,"p1":0.0,"period":8,"role":"filter"},{"indicator_id":51,"p1":0.0,"period":10,"role":"filter"},{"indicator_id":51,"p1":0.0,"period":12,"role":"filter"},{"indicator_id":51,"p1":0.0,"period":14,"role":"filter"},{"indicator_id":51,"p1":0.0,"period":16,"role":"filter"},{"indicator_id":51,"p1":0.0,"period":18,"role":"filter"},{"indicator_id":51,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":53,"p1":0.0,"period":14,"role":"filter"},{"indicator_id":53,"p1":0.0,"period":18,"role":"filter"},{"indicator_id":53,"p1":0.0,"period":22,"role":"filter"},{"indicator_id":53,"p1":0.0,"period":26,"role":"filter"},{"indicator_id":53,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":54,"p1":0.0,"period":14,"role":"filter"},{"indicator_id":54,"p1":0.0,"period":18,"role":"filter"},{"indicator_id":54,"p1":0.0,"period":22,"role":"filter"},{"indicator_id":54,"p1":0.0,"period":26,"role":"filter"},{"indicator_id":54,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":55,"p1":0.0,"period":10,"role":"filter"},{"indicator_id":55,"p1":0.0,"period":15,"role":"filter"},{"indicator_id":55,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":55,"p1":0.0,"period":25,"role":"filter"},{"indicator_id":55,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":56,"p1":0.0,"period":10,"role":"filter"},{"indicator_id":56,"p1":0.0,"period":15,"role":"filter"},{"indicator_id":56,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":56,"p1":0.0,"period":25,"role":"filter"},{"indicator_id":56,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":57,"p1":0.0,"period":10,"role":"filter"},{"indicator_id":57,"p1":0.0,"period":15,"role":"filter"},{"indicator_id":57,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":57,"p1":0.0,"period":25,"role":"filter"},{"indicator_id":57,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":58,"p1":0.0,"period":10,"role":"filter"},{"indicator_id":58,"p1":0.0,"period":15,"role":"filter"},{"indicator_id":58,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":58,"p1":0.0,"period":25,"role":"filter"},{"indicator_id":58,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":61,"p1":0.0,"period":14,"role":"filter"},{"indicator_id":61,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":61,"p1":0.0,"period":26,"role":"filter"},{"indicator_id":61,"p1":0.0,"period":32,"role":"filter"},{"indicator_id":61,"p1":0.0,"period":38,"role":"filter"},{"indicator_id":61,"p1":0.0,"period":44,"role":"filter"},{"indicator_id":61,"p1":0.0,"period":50,"role":"filter"},{"indicator_id":63,"p1":0.0,"period":5,"role":"filter"},{"indicator_id":63,"p1":0.0,"period":8,"role":"filter"},{"indicator_id":63,"p1":0.0,"period":11,"role":"filter"},{"indicator_id":63,"p1":0.0,"period":14,"role":"filter"},{"indicator_id":63,"p1":0.0,"period":17,"role":"filter"},{"indicator_id":63,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":111,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":111,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":111,"p1":0.0,"period":40,"role":"filter"},{"indicator_id":111,"p1":0.0,"period":50,"role":"filter"},{"indicator_id":111,"p1":0.0,"period":60,"role":"filter"},{"indicator_id":112,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":112,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":112,"p1":0.0,"period":40,"role":"filter"},{"indicator_id":112,"p1":0.0,"period":50,"role":"filter"},{"indicator_id":112,"p1":0.0,"period":60,"role":"filter"},{"indicator_id":113,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":113,"p1":0.0,"period":40,"role":"filter"},{"indicator_id":113,"p1":0.0,"period":50,"role":"filter"},{"indicator_id":113,"p1":0.0,"period":60,"role":"filter"},{"indicator_id":115,"p1":0.0,"period":10,"role":"filter"},{"indicator_id":115,"p1":0.0,"period":15,"role":"filter"},{"indicator_id":115,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":115,"p1":0.0,"period":25,"role":"filter"},{"indicator_id":115,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":118,"p1":0.0,"period":1,"role":"filter"},{"indicator_id":119,"p1":0.0,"period":1,"role":"filter"},{"indicator_id":62,"p1":0.0,"period":10,"role":"trend"},{"indicator_id":62,"p1":0.0,"period":15,"role":"trend"},{"indicator_id":62,"p1":0.0,"period":20,"role":"trend"},{"indicator_id":62,"p1":0.0,"period":25,"role":"trend"},{"indicator_id":62,"p1":0.0,"period":30,"role":"trend"},{"indicator_id":117,"p1":0.0,"period":1,"role":"trend"},{"indicator_id":114,"p1":10.0,"period":20,"role":"filter"},{"indicator_id":114,"p1":20.0,"period":20,"role":"filter"},{"indicator_id":114,"p1":50.0,"period":20,"role":"filter"},{"indicator_id":114,"p1":10.0,"period":30,"role":"filter"},{"indicator_id":114,"p1":20.0,"period":30,"role":"filter"},{"indicator_id":114,"p1":50.0,"period":30,"role":"filter"},{"indicator_id":114,"p1":10.0,"period":40,"role":"filter"},{"indicator_id":114,"p1":20.0,"period":40,"role":"filter"},{"indicator_id":114,"p1":50.0,"period":40,"role":"filter"},{"indicator_id":114,"p1":10.0,"period":50,"role":"filter"},{"indicator_id":114,"p1":20.0,"period":50,"role":"filter"},{"indicator_id":114,"p1":50.0,"period":50,"role":"filter"},{"indicator_id":120,"p1":0.0,"period":30,"role":"level"},{"indicator_id":120,"p1":0.0,"period":60,"role":"level"},{"indicator_id":120,"p1":0.0,"period":90,"role":"level"},{"indicator_id":120,"p1":0.0,"period":120,"role":"level"},{"indicator_id":120,"p1":0.0,"period":150,"role":"level"},{"indicator_id":120,"p1":0.0,"period":180,"role":"level"},{"indicator_id":120,"p1":0.0,"period":210,"role":"level"},{"indicator_id":120,"p1":0.0,"period":240,"role":"level"},{"indicator_id":120,"p1":0.0,"period":270,"role":"level"},{"indicator_id":120,"p1":0.0,"period":300,"role":"level"},{"indicator_id":120,"p1":0.0,"period":330,"role":"level"},{"indicator_id":120,"p1":0.0,"period":360,"role":"level"},{"indicator_id":121,"p1":0.0,"period":30,"role":"level"},{"indicator_id":121,"p1":0.0,"period":60,"role":"level"},{"indicator_id":121,"p1":0.0,"period":90,"role":"level"},{"indicator_id":121,"p1":0.0,"period":120,"role":"level"},{"indicator_id":121,"p1":0.0,"period":150,"role":"level"},{"indicator_id":121,"p1":0.0,"period":180,"role":"level"},{"indicator_id":121,"p1":0.0,"period":210,"role":"level"},{"indicator_id":121,"p1":0.0,"period":240,"role":"level"},{"indicator_id":121,"p1":0.0,"period":270,"role":"level"},{"indicator_id":121,"p1":0.0,"period":300,"role":"level"},{"indicator_id":121,"p1":0.0,"period":330,"role":"level"},{"indicator_id":121,"p1":0.0,"period":360,"role":"level"},{"indicator_id":122,"p1":0.0,"period":30,"role":"level"},{"indicator_id":122,"p1":0.0,"period":60,"role":"level"},{"indicator_id":122,"p1":0.0,"period":90,"role":"level"},{"indicator_id":122,"p1":0.0,"period":120,"role":"level"},{"indicator_id":122,"p1":0.0,"period":150,"role":"level"},{"indicator_id":122,"p1":0.0,"period":180,"role":"level"},{"indicator_id":122,"p1":0.0,"period":210,"role":"level"},{"indicator_id":122,"p1":0.0,"period":240,"role":"level"},{"indicator_id":122,"p1":0.0,"period":270,"role":"level"},{"indicator_id":122,"p1":0.0,"period":300,"role":"level"},{"indicator_id":122,"p1":0.0,"period":330,"role":"level"},{"indicator_id":122,"p1":0.0,"period":360,"role":"level"},{"indicator_id":123,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":123,"p1":0.0,"period":60,"role":"osc"},{"indicator_id":123,"p1":0.0,"period":90,"role":"osc"},{"indicator_id":123,"p1":0.0,"period":120,"role":"osc"},{"indicator_id":123,"p1":0.0,"period":150,"role":"osc"},{"indicator_id":123,"p1":0.0,"period":180,"role":"osc"},{"indicator_id":123,"p1":0.0,"period":210,"role":"osc"},{"indicator_id":123,"p1":0.0,"period":240,"role":"osc"},{"indicator_id":123,"p1":0.0,"period":270,"role":"osc"},{"indicator_id":123,"p1":0.0,"period":300,"role":"osc"},{"indicator_id":123,"p1":0.0,"period":330,"role":"osc"},{"indicator_id":123,"p1":0.0,"period":360,"role":"osc"},{"indicator_id":124,"p1":0.0,"period":30,"role":"level"},{"indicator_id":124,"p1":0.0,"period":60,"role":"level"},{"indicator_id":124,"p1":0.0,"period":90,"role":"level"},{"indicator_id":124,"p1":0.0,"period":120,"role":"level"},{"indicator_id":124,"p1":0.0,"period":150,"role":"level"},{"indicator_id":124,"p1":0.0,"period":180,"role":"level"},{"indicator_id":124,"p1":0.0,"period":210,"role":"level"},{"indicator_id":124,"p1":0.0,"period":240,"role":"level"},{"indicator_id":124,"p1":0.0,"period":270,"role":"level"},{"indicator_id":124,"p1":0.0,"period":300,"role":"level"},{"indicator_id":124,"p1":0.0,"period":330,"role":"level"},{"indicator_id":124,"p1":0.0,"period":360,"role":"level"},{"indicator_id":125,"p1":0.0,"period":30,"role":"level"},{"indicator_id":125,"p1":0.0,"period":60,"role":"level"},{"indicator_id":125,"p1":0.0,"period":90,"role":"level"},{"indicator_id":125,"p1":0.0,"period":120,"role":"level"},{"indicator_id":125,"p1":0.0,"period":150,"role":"level"},{"indicator_id":125,"p1":0.0,"period":180,"role":"level"},{"indicator_id":125,"p1":0.0,"period":210,"role":"level"},{"indicator_id":125,"p1":0.0,"period":240,"role":"level"},{"indicator_id":125,"p1":0.0,"period":270,"role":"level"},{"indicator_id":125,"p1":0.0,"period":300,"role":"level"},{"indicator_id":125,"p1":0.0,"period":330,"role":"level"},{"indicator_id":125,"p1":0.0,"period":360,"role":"level"},{"indicator_id":126,"p1":0.0,"period":30,"role":"level"},{"indicator_id":126,"p1":0.0,"period":60,"role":"level"},{"indicator_id":126,"p1":0.0,"period":90,"role":"level"},{"indicator_id":126,"p1":0.0,"period":120,"role":"level"},{"indicator_id":126,"p1":0.0,"period":150,"role":"level"},{"indicator_id":126,"p1":0.0,"period":180,"role":"level"},{"indicator_id":126,"p1":0.0,"period":210,"role":"level"},{"indicator_id":126,"p1":0.0,"period":240,"role":"level"},{"indicator_id":126,"p1":0.0,"period":270,"role":"level"},{"indicator_id":126,"p1":0.0,"period":300,"role":"level"},{"indicator_id":126,"p1":0.0,"period":330,"role":"level"},{"indicator_id":126,"p1":0.0,"period":360,"role":"level"},{"indicator_id":127,"p1":0.0,"period":10,"role":"level"},{"indicator_id":127,"p1":0.0,"period":15,"role":"level"},{"indicator_id":127,"p1":0.0,"period":20,"role":"level"},{"indicator_id":127,"p1":0.0,"period":25,"role":"level"},{"indicator_id":127,"p1":0.0,"period":30,"role":"level"},{"indicator_id":127,"p1":0.0,"period":35,"role":"level"},{"indicator_id":127,"p1":0.0,"period":40,"role":"level"},{"indicator_id":128,"p1":1.5,"period":14,"role":"level"},{"indicator_id":128,"p1":2.0,"period":14,"role":"level"},{"indicator_id":128,"p1":2.5,"period":14,"role":"level"},{"indicator_id":128,"p1":1.5,"period":18,"role":"level"},{"indicator_id":128,"p1":2.0,"period":18,"role":"level"},{"indicator_id":128,"p1":2.5,"period":18,"role":"level"},{"indicator_id":128,"p1":1.5,"period":22,"role":"level"},{"indicator_id":128,"p1":2.0,"period":22,"role":"level"},{"indicator_id":128,"p1":2.5,"period":22,"role":"level"},{"indicator_id":128,"p1":1.5,"period":26,"role":"level"},{"indicator_id":128,"p1":2.0,"period":26,"role":"level"},{"indicator_id":128,"p1":2.5,"period":26,"role":"level"},{"indicator_id":128,"p1":1.5,"period":30,"role":"level"},{"indicator_id":128,"p1":2.0,"period":30,"role":"level"},{"indicator_id":128,"p1":2.5,"period":30,"role":"level"},{"indicator_id":129,"p1":1.5,"period":14,"role":"level"},{"indicator_id":129,"p1":2.0,"period":14,"role":"level"},{"indicator_id":129,"p1":2.5,"period":14,"role":"level"},{"indicator_id":129,"p1":1.5,"period":18,"role":"level"},{"indicator_id":129,"p1":2.0,"period":18,"role":"level"},{"indicator_id":129,"p1":2.5,"period":18,"role":"level"},{"indicator_id":129,"p1":1.5,"period":22,"role":"level"},{"indicator_id":129,"p1":2.0,"period":22,"role":"level"},{"indicator_id":129,"p1":2.5,"period":22,"role":"level"},{"indicator_id":129,"p1":1.5,"period":26,"role":"level"},{"indicator_id":129,"p1":2.0,"period":26,"role":"level"},{"indicator_id":129,"p1":2.5,"period":26,"role":"level"},{"indicator_id":129,"p1":1.5,"period":30,"role":"level"},{"indicator_id":129,"p1":2.0,"period":30,"role":"level"},{"indicator_id":129,"p1":2.5,"period":30,"role":"level"},{"indicator_id":130,"p1":0.0,"period":14,"role":"level"},{"indicator_id":130,"p1":0.0,"period":20,"role":"level"},{"indicator_id":130,"p1":0.0,"period":26,"role":"level"},{"indicator_id":130,"p1":0.0,"period":32,"role":"level"},{"indicator_id":130,"p1":0.0,"period":38,"role":"level"},{"indicator_id":131,"p1":0.0,"period":14,"role":"level"},{"indicator_id":131,"p1":0.0,"period":20,"role":"level"},{"indicator_id":131,"p1":0.0,"period":26,"role":"level"},{"indicator_id":131,"p1":0.0,"period":32,"role":"level"},{"indicator_id":131,"p1":0.0,"period":38,"role":"level"},{"indicator_id":135,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":135,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":135,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":135,"p1":0.0,"period":25,"role":"osc"},{"indicator_id":135,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":136,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":136,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":136,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":136,"p1":0.0,"period":25,"role":"osc"},{"indicator_id":136,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":137,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":137,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":137,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":137,"p1":0.0,"period":25,"role":"osc"},{"indicator_id":137,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":138,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":138,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":138,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":139,"p1":0.0,"period":1,"role":"osc"},{"indicator_id":140,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":140,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":140,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":141,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":141,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":141,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":141,"p1":0.0,"period":25,"role":"osc"},{"indicator_id":141,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":142,"p1":0.0,"period":1,"role":"osc"},{"indicator_id":143,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":143,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":143,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":143,"p1":0.0,"period":25,"role":"osc"},{"indicator_id":143,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":144,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":144,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":144,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":144,"p1":0.0,"period":25,"role":"osc"},{"indicator_id":144,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":145,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":145,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":145,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":145,"p1":0.0,"period":25,"role":"osc"},{"indicator_id":145,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":146,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":146,"p1":0.0,"period":18,"role":"osc"},{"indicator_id":146,"p1":0.0,"period":22,"role":"osc"},{"indicator_id":146,"p1":0.0,"period":26,"role":"osc"},{"indicator_id":146,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":147,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":147,"p1":0.0,"period":15,"role":"osc"},{"indicator_id":147,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":147,"p1":0.0,"period":25,"role":"osc"},{"indicator_id":147,"p1":0.0,"period":30,"role":"osc"},{"indicator_id":150,"p1":0.0,"period":10,"role":"filter"},{"indicator_id":150,"p1":0.0,"period":15,"role":"filter"},{"indicator_id":150,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":150,"p1":0.0,"period":25,"role":"filter"},{"indicator_id":150,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":151,"p1":0.0,"period":10,"role":"filter"},{"indicator_id":151,"p1":0.0,"period":15,"role":"filter"},{"indicator_id":151,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":151,"p1":0.0,"period":25,"role":"filter"},{"indicator_id":151,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":152,"p1":0.0,"period":10,"role":"filter"},{"indicator_id":152,"p1":0.0,"period":15,"role":"filter"},{"indicator_id":152,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":152,"p1":0.0,"period":25,"role":"filter"},{"indicator_id":152,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":153,"p1":0.0,"period":10,"role":"filter"},{"indicator_id":153,"p1":0.0,"period":15,"role":"filter"},{"indicator_id":153,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":153,"p1":0.0,"period":25,"role":"filter"},{"indicator_id":153,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":154,"p1":0.0,"period":10,"role":"filter"},{"indicator_id":154,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":154,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":155,"p1":0.0,"period":10,"role":"filter"},{"indicator_id":155,"p1":0.0,"period":15,"role":"filter"},{"indicator_id":155,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":155,"p1":0.0,"period":25,"role":"filter"},{"indicator_id":155,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":156,"p1":0.0,"period":10,"role":"filter"},{"indicator_id":156,"p1":0.0,"period":15,"role":"filter"},{"indicator_id":156,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":156,"p1":0.0,"period":25,"role":"filter"},{"indicator_id":156,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":157,"p1":0.0,"period":10,"role":"filter"},{"indicator_id":157,"p1":0.0,"period":15,"role":"filter"},{"indicator_id":157,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":157,"p1":0.0,"period":25,"role":"filter"},{"indicator_id":157,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":158,"p1":0.0,"period":10,"role":"filter"},{"indicator_id":158,"p1":0.0,"period":15,"role":"filter"},{"indicator_id":158,"p1":0.0,"period":20,"role":"filter"},{"indicator_id":158,"p1":0.0,"period":25,"role":"filter"},{"indicator_id":158,"p1":0.0,"period":30,"role":"filter"},{"indicator_id":160,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":160,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":160,"p1":0.0,"period":12,"role":"osc"},{"indicator_id":160,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":160,"p1":0.0,"period":16,"role":"osc"},{"indicator_id":160,"p1":0.0,"period":18,"role":"osc"},{"indicator_id":160,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":161,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":161,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":161,"p1":0.0,"period":12,"role":"osc"},{"indicator_id":161,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":161,"p1":0.0,"period":16,"role":"osc"},{"indicator_id":161,"p1":0.0,"period":18,"role":"osc"},{"indicator_id":161,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":162,"p1":5.0,"period":10,"role":"osc"},{"indicator_id":162,"p1":10.0,"period":10,"role":"osc"},{"indicator_id":162,"p1":5.0,"period":12,"role":"osc"},{"indicator_id":162,"p1":10.0,"period":12,"role":"osc"},{"indicator_id":162,"p1":5.0,"period":14,"role":"osc"},{"indicator_id":162,"p1":10.0,"period":14,"role":"osc"},{"indicator_id":162,"p1":5.0,"period":16,"role":"osc"},{"indicator_id":162,"p1":10.0,"period":16,"role":"osc"},{"indicator_id":162,"p1":5.0,"period":18,"role":"osc"},{"indicator_id":162,"p1":10.0,"period":18,"role":"osc"},{"indicator_id":162,"p1":5.0,"period":20,"role":"osc"},{"indicator_id":162,"p1":10.0,"period":20,"role":"osc"},{"indicator_id":163,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":163,"p1":0.0,"period":22,"role":"osc"},{"indicator_id":163,"p1":0.0,"period":24,"role":"osc"},{"indicator_id":163,"p1":0.0,"period":26,"role":"osc"},{"indicator_id":163,"p1":0.0,"period":28,"role":"osc"},{"indicator_id":164,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":164,"p1":0.0,"period":22,"role":"osc"},{"indicator_id":164,"p1":0.0,"period":24,"role":"osc"},{"indicator_id":164,"p1":0.0,"period":26,"role":"osc"},{"indicator_id":164,"p1":0.0,"period":28,"role":"osc"},{"indicator_id":165,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":165,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":165,"p1":0.0,"period":12,"role":"osc"},{"indicator_id":165,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":165,"p1":0.0,"period":16,"role":"osc"},{"indicator_id":165,"p1":0.0,"period":18,"role":"osc"},{"indicator_id":165,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":166,"p1":0.0,"period":8,"role":"osc"},{"indicator_id":166,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":166,"p1":0.0,"period":12,"role":"osc"},{"indicator_id":166,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":166,"p1":0.0,"period":16,"role":"osc"},{"indicator_id":166,"p1":0.0,"period":18,"role":"osc"},{"indicator_id":166,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":167,"p1":0.0,"period":10,"role":"osc"},{"indicator_id":167,"p1":0.0,"period":12,"role":"osc"},{"indicator_id":167,"p1":0.0,"period":14,"role":"osc"},{"indicator_id":167,"p1":0.0,"period":16,"role":"osc"},{"indicator_id":167,"p1":0.0,"period":18,"role":"osc"},{"indicator_id":167,"p1":0.0,"period":20,"role":"osc"},{"indicator_id":168,"p1":0.0,"period":5,"role":"filter"},{"indicator_id":168,"p1":0.0,"period":8,"role":"filter"},{"indicator_id":168,"p1":0.0,"period":11,"role":"filter"},{"indicator_id":168,"p1":0.0,"period":14,"role":"filter"},{"indicator_id":168,"p1":0.0,"period":17,"role":"filter"},{"indicator_id":168,"p1":0.0,"period":20,"role":"filter"}]} diff --git a/control_plane/trading_studio/indicators/parity_harness_v1.py b/control_plane/trading_studio/indicators/parity_harness_v1.py new file mode 100644 index 0000000..e8a04b0 --- /dev/null +++ b/control_plane/trading_studio/indicators/parity_harness_v1.py @@ -0,0 +1,242 @@ +"""FEATURE_PARITY_HARNESS_V1 contracts; formula ports are deliberately external.""" + +from __future__ import annotations + +import hashlib +import json +from collections.abc import Callable, Iterable, Mapping +from dataclasses import asdict, dataclass, replace +from enum import StrEnum +from pathlib import Path +from typing import Any + +import numpy as np + +ROOT = Path(__file__).resolve().parents[3] +FROZEN_ENGINEERING_MAP_V1 = ROOT / "archaeology" / "engineering_family_map_v1.json" +FROZEN_ENGINEERING_MAP_V1_SHA256 = ( + "314a87ca468dd80e6f8bf1eaaa3e6350771ad5f53ee4f3f80db7c8949b2de1ab" +) + + +class ParityStatus(StrEnum): + PASS = "pass" + FAIL = "fail" + NOT_IMPLEMENTED = "not_implemented" + + +@dataclass(frozen=True, slots=True) +class FeatureVersion: + """One immutable implementation candidate in a parity run. + + Coverage is intentionally calculated from the versions submitted to one + run, never from the historical registry or an implied implementation pool. + """ + + feature_version: str + primitive_key: str + engineering_family: str + usage_slots: int + evaluator: Callable[..., np.ndarray] | None = None + status: ParityStatus = ParityStatus.NOT_IMPLEMENTED + + +@dataclass(frozen=True, slots=True) +class ComparisonRecord: + name: str + status: ParityStatus + expected_dtype: str + actual_dtype: str + expected_shape: tuple[int, ...] + actual_shape: tuple[int, ...] + nan_mask_mismatches: int + value_mismatches: int + reason: str | None = None + + @property + def passed(self) -> bool: + return self.status == ParityStatus.PASS + + def artifact(self) -> dict[str, object]: + return asdict(self) + + +class FrozenArtifactError(ValueError): + pass + + +def _digest(path: Path) -> str: + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def load_frozen_engineering_map(path: Path = FROZEN_ENGINEERING_MAP_V1) -> dict[str, object]: + """Load only the pinned engineering map; reject substituted archaeology.""" + if _digest(path) != FROZEN_ENGINEERING_MAP_V1_SHA256: + raise FrozenArtifactError( + "ENGINEERING_FAMILY_MAP_V1 digest does not match the frozen artifact" + ) + payload = json.loads(path.read_text(encoding="utf-8")) + if payload.get("artifact") != "ENGINEERING_FAMILY_MAP_V1" or payload.get("schema_version") != 1: + raise FrozenArtifactError("invalid ENGINEERING_FAMILY_MAP_V1 manifest") + return payload + + +def parity_manifest() -> dict[str, object]: + """Return the reproducible run contract without claiming any formula parity.""" + engineering_map = load_frozen_engineering_map() + return { + "schema_version": 1, + "artifact": "FEATURE_PARITY_HARNESS_V1_MANIFEST", + "frozen_inputs": { + "engineering_family_map": { + "path": "archaeology/engineering_family_map_v1.json", + "sha256": FROZEN_ENGINEERING_MAP_V1_SHA256, + "primitive_count": engineering_map["counts"]["primitives"], + } + }, + "oracle_windows": {"execution": "spark_offline", "network_access": "forbidden"}, + "comparison": { + "dtype": "exact", + "shape": "exact", + "nan_mask": "exact", + "state_keys": "exact", + "tolerance_by_engineering_family": {}, + "unknown_family_policy": "fail_closed_no_tolerance", + }, + "coverage": "recomputed solely from submitted FeatureVersions with status=pass", + "scope": "architecture only; no new formula ports", + } + + +def enumerate_native_evaluators( + feature_versions: Iterable[FeatureVersion], +) -> tuple[FeatureVersion, ...]: + """Return parameterized native evaluators and reject duplicate version IDs.""" + versions = tuple(feature_versions) + ids = [item.feature_version for item in versions] + if len(ids) != len(set(ids)): + raise ValueError("FeatureVersion identifiers must be unique") + return tuple(item for item in versions if item.evaluator is not None) + + +def compare_array(name: str, expected: Any, actual: Any) -> ComparisonRecord: + """Compare a feature output without numerical tolerance or dtype coercion.""" + expected_array, actual_array = np.asarray(expected), np.asarray(actual) + dtype_match = expected_array.dtype == actual_array.dtype + shape_match = expected_array.shape == actual_array.shape + if not shape_match: + return ComparisonRecord( + name, ParityStatus.FAIL, str(expected_array.dtype), str(actual_array.dtype), + expected_array.shape, actual_array.shape, 0, 0, "shape_mismatch", + ) + expected_nan = ( + np.isnan(expected_array) + if np.issubdtype(expected_array.dtype, np.inexact) + else np.zeros(expected_array.shape, bool) + ) + actual_nan = ( + np.isnan(actual_array) + if np.issubdtype(actual_array.dtype, np.inexact) + else np.zeros(actual_array.shape, bool) + ) + nan_mismatches = int(np.count_nonzero(expected_nan != actual_nan)) + values_match = dtype_match and np.array_equal(expected_array, actual_array, equal_nan=True) + matching_values = (expected_array == actual_array) | (expected_nan & actual_nan) + value_mismatches = ( + 0 + if values_match + else int(expected_array.size - np.count_nonzero(matching_values)) + ) + return ComparisonRecord( + name, ParityStatus.PASS if values_match else ParityStatus.FAIL, + str(expected_array.dtype), + str(actual_array.dtype), + expected_array.shape, + actual_array.shape, + nan_mismatches, + value_mismatches, + None if values_match else "dtype_or_value_mismatch", + ) + + +def compare_float64_ulp( + name: str, + expected: Any, + actual: Any, + *, + max_ulps: int, + allowed_indexes: frozenset[int], +) -> ComparisonRecord: + """Accept only explicitly listed finite float64 differences within a ULP bound.""" + exact = compare_array(name, expected, actual) + if exact.passed: + return exact + expected_array, actual_array = np.asarray(expected), np.asarray(actual) + if ( + expected_array.dtype != np.dtype(np.float64) + or actual_array.dtype != np.dtype(np.float64) + or expected_array.shape != actual_array.shape + or exact.nan_mask_mismatches + ): + return exact + mismatches = np.flatnonzero( + ~((expected_array == actual_array) | (np.isnan(expected_array) & np.isnan(actual_array))) + ) + if ( + not len(mismatches) + or not np.all(np.isfinite(expected_array[mismatches])) + or not np.all(np.isfinite(actual_array[mismatches])) + or any(int(index) not in allowed_indexes for index in mismatches) + ): + return exact + for index in mismatches: + expected_bits = int(np.asarray(expected_array[index]).view(np.uint64)) + actual_bits = int(np.asarray(actual_array[index]).view(np.uint64)) + expected_ordered = _ordered_float64_bits(expected_bits) + actual_ordered = _ordered_float64_bits(actual_bits) + if abs(expected_ordered - actual_ordered) > max_ulps: + return exact + return replace(exact, status=ParityStatus.PASS, reason="accepted_documented_float64_ulp_drift") + + +def _ordered_float64_bits(bits: int) -> int: + return ~bits & ((1 << 64) - 1) if bits >> 63 else bits | (1 << 63) + + +def compare_state( + expected: Mapping[str, Any], actual: Mapping[str, Any], +) -> tuple[ComparisonRecord, ...]: + """Produce auditable exact records for every state key, including missing keys.""" + records: list[ComparisonRecord] = [] + for name in sorted(set(expected) | set(actual)): + if name not in expected or name not in actual: + missing = expected.get(name, actual.get(name)) + array = np.asarray(missing) + records.append(ComparisonRecord( + name, ParityStatus.FAIL, str(array.dtype) if name in expected else "", + str(array.dtype) if name in actual else "", + array.shape if name in expected else (), + array.shape if name in actual else (), + 0, + 0, + "state_key_mismatch", + )) + else: + records.append(compare_array(name, expected[name], actual[name])) + return tuple(records) + + +def recompute_coverage(feature_versions: Iterable[FeatureVersion]) -> dict[str, object]: + """Compute coverage only over the explicitly submitted FeatureVersions.""" + versions = tuple(feature_versions) + total = sum(item.usage_slots for item in versions) + passed = tuple(item for item in versions if item.status == ParityStatus.PASS) + passed_slots = sum(item.usage_slots for item in passed) + return { + "submitted_feature_versions": len(versions), + "passed_feature_versions": len(passed), + "submitted_usage_slots": total, + "passed_usage_slots": passed_slots, + "coverage_percent": 0.0 if total == 0 else passed_slots * 100 / total, + "feature_versions": [item.feature_version for item in passed], + } diff --git a/control_plane/trading_studio/indicators/registry.py b/control_plane/trading_studio/indicators/registry.py new file mode 100644 index 0000000..91b5d6f --- /dev/null +++ b/control_plane/trading_studio/indicators/registry.py @@ -0,0 +1,193 @@ +"""Deterministic registry/universe construction and artifact serialization.""" + +from __future__ import annotations + +import hashlib +import json +from collections import Counter +from dataclasses import dataclass +from pathlib import Path + +from .definitions import ( + HISTORICAL_DEFINITIONS, + HISTORICAL_VARIANTS, + ImplementationStatus, + IndicatorDefinition, + IndicatorVariant, + Role, +) + +HISTORICAL_ARTIFACT_PATH = Path(__file__).with_name("hs22_historical_registry_v1.json") + + +@dataclass(frozen=True, slots=True) +class IndicatorUniverse: + name: str + variants: tuple[IndicatorVariant, ...] + namespace: str = "historical" + + def by_role(self, role: Role | str) -> tuple[IndicatorVariant, ...]: + return tuple(variant for variant in self.variants if variant.role == Role(role)) + + def contains(self, variant: IndicatorVariant) -> bool: + return variant in self.variants + + +@dataclass(frozen=True, slots=True) +class IndicatorRegistry: + definitions: tuple[IndicatorDefinition, ...] + variants: tuple[IndicatorVariant, ...] + + def definition(self, indicator_id: int) -> IndicatorDefinition | None: + return next((item for item in self.definitions if item.indicator_id == indicator_id), None) + + def variant(self, indicator_id: int, period: int, p1: float = 0.0) -> IndicatorVariant | None: + return next( + ( + item + for item in self.variants + if (item.indicator_id, item.period, item.p1) == (indicator_id, period, p1) + ), + None, + ) + + def role_pool(self, role: Role | str) -> tuple[IndicatorVariant, ...]: + return HS22_HISTORICAL_COMPLETE_V1.by_role(role) + + +def _all_definitions() -> tuple[IndicatorDefinition, ...]: + # Historical aliases remain metadata only. Formula execution is unavailable. + existing = {item.indicator_id: item for item in HISTORICAL_DEFINITIONS} + aliases = {25: 1, 26: None, 27: None} + for indicator_id, target in aliases.items(): + base = existing[indicator_id] + existing[indicator_id] = IndicatorDefinition( + indicator_id, + base.name, + base.role, + ImplementationStatus.ALIAS, + target, + "historical_alias; execution_refused", + ) + definitions = tuple(sorted(existing.values(), key=lambda item: item.indicator_id)) + assert len(definitions) == 145 + return definitions + + +HISTORICAL_REGISTRY = IndicatorRegistry(_all_definitions(), HISTORICAL_VARIANTS) +HS22_HISTORICAL_COMPLETE_V1 = IndicatorUniverse("HS22_HISTORICAL_COMPLETE_V1", HISTORICAL_VARIANTS) +EXPERIMENTAL_UNIVERSE = IndicatorUniverse("HS22_EXPERIMENTAL_V1", (), "experimental") +UNREGISTERED_INDICATORS = { + "MOM_JERK": "unregistered; unknown_dispatch_returns_all_nan; no_fallback", +} + + +def cohort001_universe(manifest: object | None = None) -> IndicatorUniverse: + """Build the derived universe only from canonical manifest variants. + + A missing manifest intentionally produces an empty placeholder; it never + substitutes the broad historical pool. + """ + variants: list[IndicatorVariant] = [] + if isinstance(manifest, dict): + rows = manifest.get("variants", ()) + else: + rows = () + for row in rows: + if not isinstance(row, dict): + continue + try: + candidate = IndicatorVariant( + int(row["indicator_id"]), + int(row["period"]), + float(row.get("p1", 0.0)), + Role(row["role"]), + ) + except (KeyError, TypeError, ValueError): + continue + if candidate in HISTORICAL_VARIANTS: + variants.append(candidate) + return IndicatorUniverse("HS22_COHORT001_V1", tuple(variants), "derived") + + +HS22_COHORT001_V1 = cohort001_universe() + +# This is the complete, role-sensitive Cohort001 execution surface recovered +# from the frozen oracle. It is product data, not an oracle dependency. +_HS22_REQUIRED_TRIPLES = ( + (17, 16, 2.0, "signal"), (18, 16, 2.0, "signal"), (18, 22, 2.5, "signal"), (18, 24, 2.5, "signal"), + (19, 8, 4.0, "signal"), (19, 10, 2.0, "signal"), (19, 10, 4.0, "signal"), (19, 14, 3.0, "signal"), + (21, 10, 0.0, "trigger"), (21, 14, 0.0, "trigger"), (21, 18, 0.0, "signal"), (21, 22, 0.0, "trigger"), + (24, 14, 1.0, "signal"), (30, 14, 0.0, "confirm"), (31, 5, 0.0, "confirm"), (31, 7, 0.0, "confirm"), + (31, 21, 0.0, "confirm"), (33, 16, 0.0, "confirm"), (33, 20, 0.0, "confirm"), (33, 22, 0.0, "confirm"), + (33, 24, 0.0, "confirm"), (36, 10, 0.0, "confirm"), (36, 18, 0.0, "confirm"), (36, 20, 0.0, "confirm"), + (39, 20, 0.0, "vol"), (40, 12, 0.0, "vol"), (40, 14, 0.0, "vol"), (41, 12, 0.0, "vol"), + (41, 16, 0.0, "vol"), (41, 22, 0.0, "vol"), (42, 20, 0.0, "vol"), (42, 44, 0.0, "confirm"), + (50, 8, 0.0, "trend"), (53, 18, 0.0, "vol"), (53, 30, 0.0, "vol"), (54, 22, 0.0, "trend"), + (54, 30, 0.0, "trend"), (55, 10, 0.0, "vol"), (57, 10, 0.0, "trend"), (58, 30, 0.0, "trend"), + (61, 14, 0.0, "trend"), (63, 11, 0.0, "trend"), (70, 18, 0.0, "trend"), (70, 20, 0.0, "trend"), + (71, 14, 0.0, "trend"), (71, 18, 0.0, "trend"), (72, 18, 0.0, "trend"), (73, 20, 0.0, "trend"), + (75, 26, 0.0, "trend"), (76, 23, 0.0, "trend"), (77, 1, 0.0, "vol"), (79, 30, 2.0, "trigger"), + (79, 30, 8.0, "trend"), (79, 40, 8.0, "trigger"), (79, 50, 2.0, "trigger"), (79, 50, 8.0, "trigger"), + (79, 60, 2.0, "trend"), (79, 60, 2.0, "trigger"), (81, 25, 0.0, "trigger"), (82, 30, 3.0, "trigger"), + (82, 40, 1.0, "trigger"), (91, 8, 0.0, "signal"), (91, 11, 0.0, "signal"), (92, 5, 0.0, "signal"), + (92, 17, 0.0, "signal"), (101, 8, 0.0, "trend"), (106, 8, 0.0, "confirm"), (106, 14, 0.0, "confirm"), + (112, 30, 0.0, "vol"), (113, 30, 0.0, "vol"), (114, 20, 10.0, "vol"), (114, 30, 50.0, "vol"), + (122, 60, 0.0, "trigger"), (122, 90, 0.0, "trigger"), (122, 150, 0.0, "trigger"), (122, 180, 0.0, "trigger"), + (122, 210, 0.0, "trigger"), (124, 60, 0.0, "signal"), (129, 22, 2.0, "signal"), (129, 30, 2.0, "signal"), + (152, 15, 0.0, "vol"), +) + +HS22_REQUIRED_V1 = IndicatorUniverse( + "HS22_COHORT001_REQUIRED_V1", + tuple( + IndicatorVariant( + indicator_id, + period, + p1, + {"trend": Role.TREND, "signal": Role.OSC, "trigger": Role.LEVEL, + "confirm": Role.OSC, "vol": Role.FILTER}[slot], + ) + for indicator_id, period, p1, slot in _HS22_REQUIRED_TRIPLES + ), + "derived", +) + + +def historical_artifact() -> dict[str, object]: + role_counts = Counter(item.role.value for item in HISTORICAL_VARIANTS) + return { + "schema_version": 1, + "registry": "HS22_HISTORICAL_COMPLETE_V1", + "definition_count": len(HISTORICAL_REGISTRY.definitions), + "variant_count": len(HISTORICAL_VARIANTS), + "role_counts": dict(sorted(role_counts.items())), + "definitions": [ + { + "indicator_id": item.indicator_id, + "name": item.name, + "role": item.role.value if item.role else None, + "status": item.status.value, + "alias_of": item.alias_of, + "behavior": item.behavior, + } + for item in HISTORICAL_REGISTRY.definitions + ], + "variants": [item.asdict() for item in HISTORICAL_VARIANTS], + "unknown_behavior": "all_nan; no_fallback", + "unregistered": UNREGISTERED_INDICATORS, + } + + +def historical_artifact_bytes() -> bytes: + return json.dumps( + historical_artifact(), sort_keys=True, separators=(",", ":"), allow_nan=False + ).encode() + + +def historical_artifact_digest() -> str: + return hashlib.sha256(historical_artifact_bytes()).hexdigest() + + +def write_historical_artifact(path: Path = HISTORICAL_ARTIFACT_PATH) -> None: + path.write_bytes(historical_artifact_bytes() + b"\n") diff --git a/control_plane/trading_studio/indicators/schema.py b/control_plane/trading_studio/indicators/schema.py new file mode 100644 index 0000000..3078ac8 --- /dev/null +++ b/control_plane/trading_studio/indicators/schema.py @@ -0,0 +1,76 @@ +"""Strict schema parser and state container for a five-role HS22 selection.""" + +from __future__ import annotations + +from collections.abc import Mapping, Sequence +from dataclasses import dataclass + +from .definitions import IndicatorVariant, Role +from .registry import HS22_HISTORICAL_COMPLETE_V1, IndicatorUniverse + +_ROLE_ORDER = (Role.TREND, Role.OSC, Role.LEVEL, Role.OSC, Role.FILTER) +_ROLE_NAMES = ("trend", "signal", "trigger", "confirm", "volatility") + + +class HS22SchemaError(ValueError): + pass + + +@dataclass(frozen=True, slots=True) +class HS22State: + trend: IndicatorVariant + signal: IndicatorVariant + trigger: IndicatorVariant + confirm: IndicatorVariant + volatility: IndicatorVariant + tail: tuple[float, ...] = () + + def variants(self) -> tuple[IndicatorVariant, ...]: + return (self.trend, self.signal, self.trigger, self.confirm, self.volatility) + + +def _parse_variant( + value: object, expected_role: Role, universe: IndicatorUniverse +) -> IndicatorVariant: + if isinstance(value, Mapping): + try: + variant = IndicatorVariant( + int(value["indicator_id"]), + int(value["period"]), + float(value.get("p1", 0.0)), + Role(value["role"]), + ) + except (KeyError, TypeError, ValueError) as error: + raise HS22SchemaError("invalid HS22 variant") from error + elif isinstance(value, Sequence) and not isinstance(value, (str, bytes)) and len(value) == 3: + try: + variant = IndicatorVariant(int(value[0]), int(value[1]), float(value[2]), expected_role) + except (TypeError, ValueError) as error: + raise HS22SchemaError("invalid positional HS22 variant") from error + else: + raise HS22SchemaError("HS22 variant must be an object or [id, period, p1]") + if variant.role != expected_role: + raise HS22SchemaError(f"HS22 role must be {expected_role.value}") + if not universe.contains(variant): + raise HS22SchemaError("unsupported HS22 variant; no fallback is permitted") + return variant + + +def parse_hs22( + value: object, universe: IndicatorUniverse = HS22_HISTORICAL_COMPLETE_V1 +) -> HS22State: + if isinstance(value, Mapping): + items = tuple( + _parse_variant(value.get(name), role, universe) + for name, role in zip(_ROLE_NAMES, _ROLE_ORDER, strict=True) + ) + tail = tuple(float(number) for number in value.get("tail", ())) + elif isinstance(value, Sequence) and not isinstance(value, (str, bytes)) and len(value) == 22: + items = tuple( + _parse_variant(value[index : index + 3], role, universe) + for index, role in zip(range(0, 15, 3), _ROLE_ORDER, strict=True) + ) + tail = tuple(float(number) for number in value[15:]) + else: + raise HS22SchemaError("HS22 must be a role mapping or exactly 22 positional values") + return HS22State(*items, tail=tail) diff --git a/control_plane/trading_studio/management/commands/canary_hyperscalper_cohort_001.py b/control_plane/trading_studio/management/commands/canary_hyperscalper_cohort_001.py new file mode 100644 index 0000000..a307d15 --- /dev/null +++ b/control_plane/trading_studio/management/commands/canary_hyperscalper_cohort_001.py @@ -0,0 +1,192 @@ +from __future__ import annotations + +import json +from pathlib import Path + +import numpy as np +from django.core.management.base import BaseCommand, CommandError + +from control_plane.trading_studio.cohort_materialization import ( + COHORT_MANIFEST, + DATASET_CSV, + DATASET_MANIFEST, + file_digest, + load_csv, + reconstruct_folds, + validate_dataset_manifest, + validate_manifest, + validate_rows, +) +from control_plane.trading_studio.indicators import compute_hs22_state +from control_plane.trading_studio.management.commands.materialize_hyperscalper_cohort_001 import ( + DATASET_SHA256, + DATASET_VERSION_ID, +) +from control_plane.trading_studio.management.commands.materialize_hyperscalper_cohort_001 import ( + Command as MaterializeCommand, +) +from control_plane.trading_studio.models import TradingCohort +from control_plane.trading_studio.qualification import ( + Bar, + CalibrationMethod, + calibrate_train_only, + qualification_scenario_catalog, +) +from control_plane.trading_studio.services import TradingStudioService + + +class Command(BaseCommand): + help = "Run the native HS22 Fold 1 baseline canary for frozen Cohort001." + + def add_arguments(self, parser): + parser.add_argument("artifact_root") + parser.add_argument("--cohort-id", required=True) + + def handle(self, *args, **options): + root = Path(options["artifact_root"]) + try: + cohort_manifest = self._json(root / COHORT_MANIFEST) + dataset_manifest = self._json(root / DATASET_MANIFEST) + validate_manifest(cohort_manifest, cohort=True) + validate_dataset_manifest(dataset_manifest) + dataset_path = root / DATASET_CSV + if dataset_manifest["sha256"] != file_digest(dataset_path): + raise ValueError( + "Dataset CSV file hash does not match the frozen dataset manifest." + ) + rows, headers = load_csv( + dataset_path, dataset_manifest.get("timestamp_field", "timestamp") + ) + validate_rows(rows, headers, dataset_manifest) + cohort = TradingCohort.objects.get(pk=options["cohort_id"]) + memberships = list(cohort.memberships.order_by("ordinal")) + self._validate_reconstruction( + cohort, + memberships, + cohort_manifest, + dataset_manifest, + rows, + ) + membership = memberships[0] + fold = cohort.policy_snapshot["reconstruction_v1"]["folds"][0] + state = self._native_state(rows, membership.strategy_version.genome) + train = self._bars(rows, state, fold["train"]) + replay = self._bars(rows, state, fold["test"]) + calibration = calibrate_train_only( + train, + method=CalibrationMethod.RAW, + fold=fold["fold"], + train_start=train[0].at, + train_end=rows[fold["embargo"]["start_index"]]["timestamp"], + source_record_ids=(str(membership.id),), + source_combo=json.dumps( + membership.strategy_version.genome["combo"], + separators=(",", ":"), + ), + ) + run = TradingStudioService().run_qualification_canary( + strategy_version=membership.strategy_version, + dataset_version=cohort.dataset_version, + fold=fold["fold"], + scenario=qualification_scenario_catalog()["BASELINE"], + runner_name="canary_hyperscalper_cohort_001", + bars=replay, + calibration=calibration, + ) + except ( + KeyError, + TradingCohort.DoesNotExist, + OSError, + ValueError, + json.JSONDecodeError, + ) as error: + raise CommandError(str(error)) from error + self.stdout.write(json.dumps({"qualification_run_id": str(run.id), "mode": "CANARY_ONLY"})) + + @staticmethod + def _json(path: Path) -> dict: + return json.loads(path.read_text(encoding="utf-8")) + + @staticmethod + def _validate_reconstruction(cohort, memberships, cohort_manifest, dataset_manifest, rows): + reconstruction = cohort.policy_snapshot.get("reconstruction_v1") + if not isinstance(reconstruction, dict): + raise ValueError("Cohort has no validated reconstruction_v1 policy.") + if ( + cohort.dataset_version_id != DATASET_VERSION_ID + or dataset_manifest["sha256"] != DATASET_SHA256 + or reconstruction.get("cohort_manifest", {}).get("manifest_sha256") + != cohort_manifest["manifest_sha256"] + or reconstruction.get("dataset_manifest", {}).get("sha256") + != dataset_manifest["sha256"] + or reconstruction.get("provenance") != "RECONSTRUCTED_FROM_FROZEN_SPEC_V1" + or reconstruction.get("folds") + != reconstruct_folds(rows, dataset_manifest.get("timestamp_field", "timestamp")) + ): + raise ValueError("Cohort reconstruction_v1 does not match the validated artifact.") + members = cohort_manifest["members"] + if len(memberships) != 20 or [member.ordinal for member in memberships] != list( + range(1, 21) + ): + raise ValueError("Cohort does not contain the required 20 ordered memberships.") + for membership, member in zip(memberships, members, strict=True): + if ( + membership.id != MaterializeCommand._member_id(member) + or membership.strategy_version.fingerprint + != MaterializeCommand._fingerprint(member) + or membership.metadata.get("selection_position") != member["rank"] + ): + raise ValueError("Cohort membership does not match the frozen semantic member.") + + @staticmethod + def _native_state(rows, genome): + try: + combo = genome["combo"] + except (KeyError, TypeError) as error: + raise ValueError("First frozen strategy genome has no HS22 combo.") from error + if not isinstance(combo, (list, tuple)) or len(combo) != 22: + raise ValueError("First frozen strategy genome has no 22-field HS22 combo.") + close, high, low, volume = ( + np.asarray([row[field] for row in rows], dtype=np.float64) + for field in ("close", "high", "low", "volume") + ) + state = compute_hs22_state(combo, close, high, low, volume) + valid = ( + np.isfinite(state["trigger"]) + & np.isfinite(state["confirm"]) + & np.isfinite(state["vol"]) + ) + volatility = state["vol"][np.isfinite(state["vol"])] + if not len(volatility): + raise ValueError("Native HS22 state contains no finite volatility values.") + threshold = np.sort(volatility)[ + min(int(float(combo[21]) / 100 * len(volatility)), len(volatility) - 1) + ] + valid &= state["vol"] >= threshold + signal = state["signal_color"] + trend = state["trend_color"] + flips = (signal != np.roll(signal, 1)) & (signal != 0) + long = valid & flips & (signal == 1) & (trend == 1) & (close > state["trigger"]) + long &= (float(combo[17]) <= state["confirm"]) & (state["confirm"] <= float(combo[18])) + short = valid & flips & (signal == -1) & (trend == -1) & (close < state["trigger"]) + short &= (float(combo[19]) <= state["confirm"]) & (state["confirm"] <= float(combo[20])) + state["decision"] = long.astype(np.int8) - short.astype(np.int8) + return state + + @staticmethod + def _bars(rows, state, window): + start, end = window["start_index"], window["end_index"] + 1 + names = ("trend", "signal", "trigger", "confirm", "vol", "trend_color", "signal_color") + return [ + Bar( + at=row["timestamp"], + open=row["open"], + high=row["high"], + low=row["low"], + close=row["close"], + signal=int(state["decision"][index]) or None, + context=tuple(float(state[name][index]) for name in names), + reference=f"hs22-native:{index}", + ) + for index, row in enumerate(rows[start:end], start=start) + ] diff --git a/control_plane/trading_studio/management/commands/cohort_qualification_hyperscalper_001.py b/control_plane/trading_studio/management/commands/cohort_qualification_hyperscalper_001.py new file mode 100644 index 0000000..53b22b6 --- /dev/null +++ b/control_plane/trading_studio/management/commands/cohort_qualification_hyperscalper_001.py @@ -0,0 +1,395 @@ +from __future__ import annotations + +import json +from collections import Counter +from dataclasses import asdict, fields +from pathlib import Path +from typing import Any + +from django.core.management.base import BaseCommand, CommandError +from django.db import transaction + +from control_plane.trading_studio.cohort_materialization import ( + COHORT_MANIFEST, + DATASET_CSV, + DATASET_MANIFEST, + digest, + file_digest, + load_csv, + validate_dataset_manifest, + validate_manifest, + validate_rows, +) +from control_plane.trading_studio.management.commands.canary_hyperscalper_cohort_001 import ( + Command as CanaryCommand, +) +from control_plane.trading_studio.management.commands.specimen_hyperscalper_cohort_001 import ( + Command as SpecimenCommand, + SCENARIO_NAMES, +) +from control_plane.trading_studio.models import QualificationReplayRun, TradingCohort +from control_plane.trading_studio.qualification import ( + CalibrationMethod, + DEQPrimitives, + calibrate_train_only, + qualification_scenario_catalog, +) +from control_plane.trading_studio.services import TradingStudioService + + +RUNNER_NAME = "cohort_qualification_hyperscalper_001:v1" +RUNNER_PREFIX = "cohort_qualification_hyperscalper_001" +CONTRACT = "Cohort001-qualification-v1" +SPECIMEN_CONTRACT = "Cohort001-first-member-specimen-v1" + + +class Command(BaseCommand): + help = "Qualify frozen HyperScalper Cohort001 members 2 through 20 with persisted HS22 replays." + + def add_arguments(self, parser): + parser.add_argument("artifact_root") + parser.add_argument("--cohort-id", required=True) + parser.add_argument("--specimen-report-path", required=True) + parser.add_argument("--specimen-report-sha", required=True) + parser.add_argument("--report-path", default="qualification_cohort_001_v1.json") + parser.add_argument("--indicator-expansion-path", default="indicator_expansion_brief.md") + + def handle(self, *args, **options): + root = Path(options["artifact_root"]) + specimen_path = Path(options["specimen_report_path"]) + report_path = Path(options["report_path"]) + brief_path = Path(options["indicator_expansion_path"]) + try: + cohort_manifest = self._json(root / COHORT_MANIFEST) + dataset_manifest = self._json(root / DATASET_MANIFEST) + validate_manifest(cohort_manifest, cohort=True) + validate_dataset_manifest(dataset_manifest) + dataset_path = root / DATASET_CSV + if dataset_manifest["sha256"] != file_digest(dataset_path): + raise ValueError("Dataset CSV file hash does not match the frozen dataset manifest.") + rows, headers = load_csv( + dataset_path, dataset_manifest.get("timestamp_field", "timestamp") + ) + validate_rows(rows, headers, dataset_manifest) + specimen_sha256 = file_digest(specimen_path) + expected_specimen_sha256 = options["specimen_report_sha"] + if ( + len(expected_specimen_sha256) != 64 + or any(character not in "0123456789abcdef" for character in expected_specimen_sha256) + or specimen_sha256 != expected_specimen_sha256 + ): + raise ValueError("Specimen report SHA does not match the externally frozen SHA.") + specimen = self._json(specimen_path) + catalog = qualification_scenario_catalog() + if tuple(catalog) != SCENARIO_NAMES or len(catalog) != 13: + raise ValueError( + "QualificationReplayV1 must provide the frozen 13-scenario catalog." + ) + config_sha256 = digest({name: asdict(spec) for name, spec in catalog.items()}) + self._validate_specimen(specimen) + protocol_identity = { + "cohort_manifest_sha256": cohort_manifest["manifest_sha256"], + "dataset_sha256": dataset_manifest["sha256"], + "qualification_scenario_catalog_sha256": config_sha256, + "specimen_report_sha256": specimen_sha256, + "runner_name": RUNNER_NAME, + } + cohort = TradingCohort.objects.get(pk=options["cohort_id"]) + memberships = list(cohort.memberships.select_related("strategy_version").order_by("ordinal")) + CanaryCommand._validate_reconstruction( + cohort, memberships, cohort_manifest, dataset_manifest, rows + ) + self._validate_runner_versions(memberships, cohort.dataset_version_id) + except ( + KeyError, + TradingCohort.DoesNotExist, + OSError, + ValueError, + json.JSONDecodeError, + ) as error: + raise CommandError(str(error)) from error + + member_reports = [] + try: + # A cohort qualification is all-or-nothing; reruns reuse the same immutable identity. + with transaction.atomic(): + service = TradingStudioService() + for membership in memberships[1:]: + state = CanaryCommand._native_state( + rows, membership.strategy_version.genome + ) + folds = [] + for fold in cohort.policy_snapshot["reconstruction_v1"]["folds"]: + train = CanaryCommand._bars(rows, state, fold["train"]) + replay = CanaryCommand._bars(rows, state, fold["test"]) + calibration = self._calibration(membership, fold, rows, train) + scenarios = [] + for name in SCENARIO_NAMES: + run, reused = self._run_or_reuse( + service, + membership, + cohort, + fold, + catalog[name], + replay, + calibration, + protocol_identity, + ) + scenario = SpecimenCommand._scenario_report(run) + scenario["persistence"] = "REUSED" if reused else "CREATED" + scenarios.append(scenario) + folds.append({"fold": fold["fold"], "scenarios": scenarios}) + member_reports.append( + { + "ordinal": membership.ordinal, + "member_id": str(membership.id), + "strategy_version_id": str(membership.strategy_version_id), + "folds": folds, + } + ) + except ValueError as error: + raise CommandError(str(error)) from error + + report = self._report( + cohort, + member_reports, + cohort_manifest["manifest_sha256"], + dataset_manifest["sha256"], + config_sha256, + specimen_sha256, + ) + brief = self._indicator_brief(report["machine"]["indicator_expansion"]) + try: + for path, payload in ((report_path, json.dumps(report, sort_keys=True, indent=2)),): + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(payload, encoding="utf-8") + brief_path.parent.mkdir(parents=True, exist_ok=True) + brief_path.write_text(brief, encoding="utf-8") + except OSError as error: + raise CommandError(str(error)) from error + self.stdout.write(json.dumps(report, sort_keys=True, ensure_ascii=True)) + + @staticmethod + def _json(path: Path) -> dict[str, Any]: + return json.loads(path.read_text(encoding="utf-8")) + + @staticmethod + def _validate_specimen(report: dict[str, Any]) -> None: + machine = report.get("machine", {}) + if ( + machine.get("contract") != SPECIMEN_CONTRACT + or machine.get("member_ordinal") != 1 + or machine.get("fold_count") != 4 + or machine.get("scenario_count_per_fold") != 13 + ): + raise ValueError( + "Specimen report is not the frozen Cohort001 ordinal-one 4x13 report." + ) + folds = machine.get("folds") + if not isinstance(folds, list) or len(folds) != 4: + raise ValueError("Legacy specimen report is missing its four fold records.") + required_scenario = { + "qualification_run_id", + "scenario", + "summary", + "ledger", + "ledger_reconciliation", + "deq", + "rescue", + } + required_ledger = { + "gross_pnl", + "net_pnl", + "entry_commission", + "exit_commission", + "entry_slippage", + "exit_slippage", + "funding", + "other_cost", + "deq", + } + for fold in folds: + scenarios = fold.get("scenarios") if isinstance(fold, dict) else None + if not isinstance(fold, dict) or not fold.get("fold") or not isinstance(scenarios, list): + raise ValueError("Legacy specimen report fold fields are incomplete.") + if len(scenarios) != 13 or [item.get("scenario") for item in scenarios] != list( + SCENARIO_NAMES + ): + raise ValueError("Legacy specimen report scenario catalog does not match the frozen 13.") + for scenario in scenarios: + ledger = scenario.get("ledger") if isinstance(scenario, dict) else None + if not isinstance(scenario, dict) or required_scenario - set(scenario): + raise ValueError("Legacy specimen report scenario fields are incomplete.") + if not isinstance(scenario["summary"], dict) or not isinstance(ledger, list): + raise ValueError("Legacy specimen report scenario summary or ledger is invalid.") + if any(not isinstance(row, dict) or required_ledger - set(row) for row in ledger): + raise ValueError("Legacy specimen report ledger fields are incomplete.") + + @staticmethod + def _validate_runner_versions(memberships, dataset_version_id) -> None: + strategy_ids = [member.strategy_version_id for member in memberships[1:]] + versions = QualificationReplayRun.objects.filter( + strategy_version_id__in=strategy_ids, + dataset_version_id=dataset_version_id, + runner_name__startswith=RUNNER_PREFIX, + ).exclude(runner_name=RUNNER_NAME) + if versions.exists(): + raise ValueError("Qualification cohort refuses mixed runner versions.") + + @staticmethod + def _calibration(membership, fold, rows, train): + return calibrate_train_only( + train, + method=CalibrationMethod.RAW, + fold=fold["fold"], + train_start=train[0].at, + train_end=rows[fold["embargo"]["start_index"]]["timestamp"], + source_record_ids=(str(membership.id),), + source_combo=json.dumps( + membership.strategy_version.genome["combo"], separators=(",", ":") + ), + allow_empty_raw=True, + ) + + @staticmethod + def _run_or_reuse( + service, membership, cohort, fold, scenario, replay, calibration, protocol_identity + ): + existing = QualificationReplayRun.objects.filter( + strategy_version=membership.strategy_version, + dataset_version=cohort.dataset_version, + fold=fold["fold"], + scenario_name=scenario.name, + runner_name=RUNNER_NAME, + input_hash=calibration.input_hash, + ).first() + expected_configuration = TradingStudioService.qualification_configuration( + scenario, + protocol_identity=protocol_identity, + require_protocol_identity=True, + ) + if existing: + if ( + existing.replay_mode != "CANARY_ONLY" + or existing.calibration + != TradingStudioService._json_safe(asdict(calibration)) + or existing.configuration != expected_configuration + ): + raise ValueError("Persisted qualification identity has incompatible protocol inputs.") + return existing, True + return ( + service.run_qualification_canary( + strategy_version=membership.strategy_version, + dataset_version=cohort.dataset_version, + fold=fold["fold"], + scenario=scenario, + runner_name=RUNNER_NAME, + bars=replay, + calibration=calibration, + protocol_identity=protocol_identity, + require_protocol_identity=True, + ), + False, + ) + + @staticmethod + def _report( + cohort, members, manifest_sha256, dataset_sha256, config_sha256, specimen_sha256 + ): + scenarios = [ + scenario + for member in members + for fold in member["folds"] + for scenario in fold["scenarios"] + ] + expansion = Command._indicator_expansion(scenarios) + machine = { + "contract": CONTRACT, + "cohort_id": str(cohort.id), + "member_ordinals": [member["ordinal"] for member in members], + "fold_count": 4, + "scenario_count_per_fold": 13, + "expected_persisted_runs": len(members) * 4 * 13, + "protocol_identity": { + "cohort_manifest_sha256": manifest_sha256, + "dataset_sha256": dataset_sha256, + "qualification_scenario_catalog_sha256": config_sha256, + "specimen_report_sha256": specimen_sha256, + "runner_name": RUNNER_NAME, + }, + "members": members, + "indicator_expansion": expansion, + } + return { + "machine": machine, + "human": { + "scope": "Cohort001 ordinals 2 through 20; ordinal 1 remains the frozen specimen.", + "persisted_runs": len(scenarios), + "ledger_reconciled": all( + scenario["ledger_reconciliation"]["consistent"] for scenario in scenarios + ), + "runner_version": RUNNER_NAME, + "indicator_expansion_status": expansion["status"], + }, + } + + @staticmethod + def _indicator_expansion(scenarios): + ledger = [row for scenario in scenarios for row in scenario["ledger"]] + exit_classes = Counter(row["exit_reason"] for row in ledger) + direction_classes = Counter( + "LONG" if row["take_profit_price"] > row["entry_execution_price"] else "SHORT" + for row in ledger + ) + pnl_classes = Counter( + "WIN" if row["net_pnl"] > 0 else "LOSS" if row["net_pnl"] < 0 else "BREAKEVEN" + for row in ledger + ) + deq = {} + for field in fields(DEQPrimitives): + values = [ + row["deq"][field.name] + for row in ledger + if row["deq"][field.name] is not None + ] + payload = {"available_count": len(values), "missing_count": len(ledger) - len(values)} + if values and isinstance(values[0], bool): + payload["classes"] = {"true": sum(values), "false": len(values) - sum(values)} + elif values: + payload["distribution"] = { + "min": min(values), "max": max(values), "mean": sum(values) / len(values) + } + else: + payload["status"] = "INSUFFICIENT" + deq[field.name] = payload + return { + "status": "AVAILABLE" if ledger else "INSUFFICIENT", + "ledger_trade_count": len(ledger), + "classes": { + "exit_reason": dict(sorted(exit_classes.items())), + "direction": dict(sorted(direction_classes.items())), + "net_pnl": dict(sorted(pnl_classes.items())), + }, + "deq_distributions": deq, + } + + @staticmethod + def _indicator_brief(expansion): + lines = [ + "# Indicator Expansion Brief", + "", + f"Status: {expansion['status']}", + f"Persisted ledger trades: {expansion['ledger_trade_count']}", + "", + "## Required classes", + ] + for name, values in expansion["classes"].items(): + lines.append(f"- {name}: {json.dumps(values, sort_keys=True)}") + lines.extend(["", "## DEQ distributions"]) + for name, value in expansion["deq_distributions"].items(): + lines.append(f"- {name}: {json.dumps(value, sort_keys=True)}") + if expansion["status"] == "INSUFFICIENT": + lines.extend( + ["", "No ledger observations were emitted; distributions are insufficient."] + ) + return "\n".join(lines) + "\n" diff --git a/control_plane/trading_studio/management/commands/materialize_hyperscalper_cohort_001.py b/control_plane/trading_studio/management/commands/materialize_hyperscalper_cohort_001.py new file mode 100644 index 0000000..ffe917f --- /dev/null +++ b/control_plane/trading_studio/management/commands/materialize_hyperscalper_cohort_001.py @@ -0,0 +1,221 @@ +from __future__ import annotations + +import hashlib +import json +from pathlib import Path +from uuid import NAMESPACE_URL, UUID, uuid5 + +from django.core.management.base import BaseCommand, CommandError +from django.db import transaction + +from control_plane.trading_studio.cohort_materialization import ( + COHORT_MANIFEST, + DATASET_CSV, + DATASET_MANIFEST, + PROVENANCE, + file_digest, + load_csv, + reconstruct_folds, + validate_dataset_manifest, + validate_manifest, + validate_rows, + validate_selection_source, +) +from control_plane.trading_studio.models import ( + CohortMembership, + MarketDatasetVersion, + Strategy, + StrategyVersion, + TradingCohort, +) + +DATASET_VERSION_ID = UUID("1f224db9-cbb8-4aec-8575-98c4b0279a83") +DATASET_SHA256 = "7fb56bb05b0edc2348407765cd693efadf334307c25877dfb52acfe4221e5d00" +UUID_NAMESPACE = uuid5(NAMESPACE_URL, "artifex:hyperscalper-revalidation-001") + + +class Command(BaseCommand): + help = "Recover frozen HyperScalper Cohort 001 from its CSV artifact." + + def add_arguments(self, parser): + parser.add_argument("artifact_root") + parser.add_argument("--selection-source", required=True) + parser.add_argument("--cohort-id", required=True, type=UUID) + + def handle(self, *args, **options): + root = Path(options["artifact_root"]) + selection_path = Path(options["selection_source"]) + try: + cohort_manifest = self._json(root / COHORT_MANIFEST) + dataset_manifest = self._json(root / DATASET_MANIFEST) + validate_manifest(cohort_manifest, cohort=True) + validate_dataset_manifest(dataset_manifest) + if dataset_manifest["sha256"] != DATASET_SHA256: + raise ValueError( + "Dataset manifest SHA does not match the authorized frozen artifact." + ) + selection = self._json(selection_path) + selection_sha256 = validate_selection_source(cohort_manifest, selection, selection_path) + rows, headers = load_csv( + root / DATASET_CSV, dataset_manifest.get("timestamp_field", "timestamp") + ) + if dataset_manifest["sha256"] != file_digest(root / DATASET_CSV): + raise ValueError( + "Dataset CSV file hash does not match the frozen dataset manifest." + ) + validate_rows(rows, headers, dataset_manifest) + folds = reconstruct_folds(rows, dataset_manifest.get("timestamp_field", "timestamp")) + strategies = cohort_manifest["members"] + if len(strategies) != 20 or any(len(member["combo"]) != 22 for member in strategies): + raise ValueError( + "Frozen cohort must contain 20 ordered members with 22-field combos." + ) + if not isinstance(selection, dict): + raise ValueError("Selection source must be a JSON object.") + except (KeyError, OSError, ValueError, json.JSONDecodeError) as error: + raise CommandError(str(error)) from error + + snapshot = { + "cohort_manifest": cohort_manifest, + "dataset_manifest": dataset_manifest, + "folds": folds, + "provenance": PROVENANCE, + "artifact_refs": { + "cohort_manifest": f"artifact://{COHORT_MANIFEST}", + "dataset_manifest": f"artifact://{DATASET_MANIFEST}", + "dataset": f"artifact://{DATASET_CSV}", + "selection_source": cohort_manifest["source_report"], + "selection_source_observed_sha256": selection_sha256, + }, + } + with transaction.atomic(): + version = self._dataset(root, dataset_manifest, rows) + project = version.dataset.trading_project + try: + cohort = TradingCohort.objects.get(pk=options["cohort_id"]) + except TradingCohort.DoesNotExist as error: + raise CommandError("The authorized pre-existing cohort does not exist.") from error + if ( + cohort.dataset_version_id != version.id + or self._historic_manifest_sha(cohort.policy_snapshot) + != cohort_manifest["manifest_sha256"] + ): + raise CommandError( + "Existing cohort frozen core identity conflicts with the artifact." + ) + policy = dict(cohort.policy_snapshot) + if policy.get("reconstruction_v1") != snapshot: + policy["reconstruction_v1"] = snapshot + cohort.policy_snapshot = policy + cohort.save(update_fields=["policy_snapshot", "updated_at"]) + for ordinal, item in enumerate(strategies, start=1): + strategy, version = self._strategy(project, item) + member_id = self._member_id(item) + member, member_created = CohortMembership.objects.get_or_create( + id=member_id, + defaults={ + "cohort": cohort, + "strategy_version": version, + "ordinal": ordinal, + "member_id": member_id, + "provenance": PROVENANCE, + "metadata": { + "selection_position": item["rank"], + "source_strategy_id": item["source_strategy_id"], + "base_family": item["base_family"], + "combo": item["combo"], + }, + }, + ) + if not member_created and ( + member.cohort_id != cohort.id + or member.strategy_version_id != version.id + or member.ordinal != ordinal + ): + raise CommandError("Frozen CohortMembership ID exists with different content.") + self.stdout.write(json.dumps({"cohort_id": str(cohort.id), "reconstructed": True})) + + @staticmethod + def _json(path: Path) -> dict: + return json.loads(path.read_text(encoding="utf-8")) + + @staticmethod + def _dataset(root: Path, manifest: dict, rows: list[dict]): + try: + version = MarketDatasetVersion.objects.select_related("dataset__trading_project").get( + pk=DATASET_VERSION_ID + ) + except MarketDatasetVersion.DoesNotExist as error: + raise CommandError( + "The authorized pre-existing dataset version does not exist." + ) from error + if ( + version.dataset.trading_project.slug != "crypto-hyperscalper" + or version.content_hash != manifest["sha256"] + or version.record_count != len(rows) + or Path(version.reference).resolve() != (root / DATASET_CSV).resolve() + or version.fields != manifest["fields"] + or version.start_at != rows[0]["timestamp"] + or version.end_at != rows[-1]["timestamp"] + or int(rows[0]["timestamp"].timestamp()) != manifest["first_timestamp"] + or int(rows[-1]["timestamp"].timestamp()) != manifest["last_timestamp"] + ): + raise CommandError( + "Existing dataset version does not match the frozen artifact identity." + ) + return version + + @staticmethod + def _historic_manifest_sha(policy: dict) -> str | None: + return ( + policy.get("manifest_sha256") + or policy.get("cohort_manifest", {}).get("manifest_sha256") + or policy.get("frozen_manifest", {}).get("manifest_sha256") + ) + + @staticmethod + def _strategy(project, item): + fingerprint = Command._fingerprint(item) + strategy, _ = Strategy.objects.get_or_create( + id=uuid5(UUID_NAMESPACE, f"strategy:{fingerprint}"), + defaults={ + "trading_project": project, + "name": item["source_name"], + "strategy_class": "HS22", + }, + ) + version_defaults = { + "strategy": strategy, + "version": "frozen-v1", + "genome": {"base_family": item["base_family"], "combo": item["combo"]}, + "fingerprint": fingerprint, + } + version, created = StrategyVersion.objects.get_or_create( + id=uuid5(UUID_NAMESPACE, f"strategy-version:{fingerprint}"), + defaults=version_defaults, + ) + if created: + version.immutable = True + version.save(update_fields=["immutable", "updated_at"]) + elif not version.immutable or any( + getattr(version, field) != value for field, value in version_defaults.items() + ): + raise CommandError("Frozen strategy version exists with different immutable identity.") + if strategy.trading_project_id != project.id or version.strategy_id != strategy.id: + raise CommandError("Frozen strategy ID exists with different content.") + return strategy, version + + @staticmethod + def _fingerprint(member: dict) -> str: + projection = { + "selection_position": member["rank"], + "source_strategy_id": member["source_strategy_id"], + "base_family": member["base_family"], + "combo": member["combo"], + } + payload = json.dumps(projection, sort_keys=True, ensure_ascii=True, separators=(",", ":")) + return hashlib.sha256(payload.encode()).hexdigest() + + @staticmethod + def _member_id(member: dict) -> UUID: + return uuid5(UUID_NAMESPACE, f"membership:{Command._fingerprint(member)}") diff --git a/control_plane/trading_studio/management/commands/specimen_hyperscalper_cohort_001.py b/control_plane/trading_studio/management/commands/specimen_hyperscalper_cohort_001.py new file mode 100644 index 0000000..c54f6b3 --- /dev/null +++ b/control_plane/trading_studio/management/commands/specimen_hyperscalper_cohort_001.py @@ -0,0 +1,236 @@ +from __future__ import annotations + +import json +from dataclasses import fields +from pathlib import Path +from typing import Any + +from django.core.management.base import BaseCommand, CommandError + +from control_plane.trading_studio.cohort_materialization import ( + COHORT_MANIFEST, + DATASET_CSV, + DATASET_MANIFEST, + file_digest, + load_csv, + validate_dataset_manifest, + validate_manifest, + validate_rows, +) +from control_plane.trading_studio.management.commands.canary_hyperscalper_cohort_001 import ( + Command as CanaryCommand, +) +from control_plane.trading_studio.models import TradingCohort +from control_plane.trading_studio.qualification import ( + CalibrationMethod, + DEQPrimitives, + calibrate_train_only, + qualification_scenario_catalog, +) +from control_plane.trading_studio.services import TradingStudioService + +SCENARIO_NAMES = ( + "BASELINE", + "SLIPPAGE_ADVERSE_2BP", + "TOTAL_COST_6BP", + "TOTAL_COST_10BP", + "TOTAL_COST_15BP", + "PESSIMISTIC_SAME_BAR", + "ENTRY_DELAY_PLUS_ONE_BAR", + "WEEKDAYS_ONLY", + "ALL_DAYS", + "STOP_WIDTH_100", + "STOP_WIDTH_75", + "STOP_WIDTH_50", + "STOP_WIDTH_25", +) +RUNNER_NAME = "specimen_hyperscalper_cohort_001" + + +class Command(BaseCommand): + help = "Persist and report the first Cohort001 member across all reconstructed folds." + + def add_arguments(self, parser): + parser.add_argument("artifact_root") + parser.add_argument("--cohort-id", required=True) + parser.add_argument("--report-path", required=True) + + def handle(self, *args, **options): + root = Path(options["artifact_root"]) + report_path = Path(options["report_path"]) + try: + cohort_manifest = self._json(root / COHORT_MANIFEST) + dataset_manifest = self._json(root / DATASET_MANIFEST) + validate_manifest(cohort_manifest, cohort=True) + validate_dataset_manifest(dataset_manifest) + dataset_path = root / DATASET_CSV + if dataset_manifest["sha256"] != file_digest(dataset_path): + raise ValueError( + "Dataset CSV file hash does not match the frozen dataset manifest." + ) + rows, headers = load_csv( + dataset_path, dataset_manifest.get("timestamp_field", "timestamp") + ) + validate_rows(rows, headers, dataset_manifest) + cohort = TradingCohort.objects.get(pk=options["cohort_id"]) + memberships = list(cohort.memberships.order_by("ordinal")) + CanaryCommand._validate_reconstruction( + cohort, memberships, cohort_manifest, dataset_manifest, rows + ) + membership = memberships[0] # Specimen scope is deliberately limited to rank one. + state = CanaryCommand._native_state(rows, membership.strategy_version.genome) + catalog = qualification_scenario_catalog() + if tuple(catalog) != SCENARIO_NAMES: + raise ValueError( + "QualificationReplayV1 scenario catalog differs from specimen contract." + ) + + fold_reports = [] + service = TradingStudioService() + for fold in cohort.policy_snapshot["reconstruction_v1"]["folds"]: + train = CanaryCommand._bars(rows, state, fold["train"]) + replay = CanaryCommand._bars(rows, state, fold["test"]) + calibration = calibrate_train_only( + train, + method=CalibrationMethod.RAW, + fold=fold["fold"], + train_start=train[0].at, + train_end=rows[fold["embargo"]["start_index"]]["timestamp"], + source_record_ids=(str(membership.id),), + source_combo=json.dumps( + membership.strategy_version.genome["combo"], separators=(",", ":") + ), + ) + scenarios = [] + for name in SCENARIO_NAMES: + run = service.run_qualification_canary( + strategy_version=membership.strategy_version, + dataset_version=cohort.dataset_version, + fold=fold["fold"], + scenario=catalog[name], + runner_name=RUNNER_NAME, + bars=replay, + calibration=calibration, + ) + scenarios.append(self._scenario_report(run)) + fold_reports.append({"fold": fold["fold"], "scenarios": scenarios}) + + report = self._report(cohort, membership, fold_reports) + report_path.parent.mkdir(parents=True, exist_ok=True) + report_path.write_text( + json.dumps(report, sort_keys=True, indent=2, ensure_ascii=True), encoding="utf-8" + ) + except ( + KeyError, + TradingCohort.DoesNotExist, + OSError, + ValueError, + json.JSONDecodeError, + ) as error: + raise CommandError(str(error)) from error + self.stdout.write(json.dumps(report, sort_keys=True, ensure_ascii=True)) + + @staticmethod + def _json(path: Path) -> dict[str, Any]: + return json.loads(path.read_text(encoding="utf-8")) + + @staticmethod + def _scenario_report(run) -> dict[str, Any]: + ledger = [row.result for row in run.ledger_rows.order_by("sequence")] + reconciliation = Command._reconcile(run.summary, ledger) + return { + "qualification_run_id": str(run.id), + "scenario": run.scenario_name, + "summary": run.summary, + "ledger": ledger, + "ledger_reconciliation": reconciliation, + "deq": Command._deq_aggregate(ledger), + "rescue": run.summary["rescue"], + } + + @staticmethod + def _reconcile(summary: dict[str, Any], ledger: list[dict[str, Any]]) -> dict[str, Any]: + sums = { + "gross_pnl": sum(row["gross_pnl"] for row in ledger), + "net_pnl": sum(row["net_pnl"] for row in ledger), + "commissions": sum(row["entry_commission"] + row["exit_commission"] for row in ledger), + "slippage": sum(row["entry_slippage"] + row["exit_slippage"] for row in ledger), + "funding": sum(row["funding"] for row in ledger), + "other_cost": sum(row["other_cost"] for row in ledger), + } + rescue = summary["rescue"] + rows_consistent = all( + abs( + row["net_pnl"] + - ( + row["gross_pnl"] + - row["entry_commission"] + - row["exit_commission"] + - row["funding"] + - row["other_cost"] + ) + ) + <= 1e-9 + for row in ledger + ) + consistent = ( + rows_consistent + and summary["ledger_count"] == len(ledger) + and all( + abs(summary[name] - value) <= 1e-9 + for name, value in sums.items() + if name in summary + ) + and all(abs(rescue[name] - value) <= 1e-9 for name, value in sums.items()) + ) + return { + "consistent": consistent, + "row_pnl_consistent": rows_consistent, + "ledger_count": len(ledger), + "totals": sums, + } + + @staticmethod + def _deq_aggregate(ledger: list[dict[str, Any]]) -> dict[str, Any]: + result: dict[str, Any] = {"trade_count": len(ledger), "fields": {}} + for field in fields(DEQPrimitives): + name = field.name + values = [row["deq"][name] for row in ledger if row["deq"][name] is not None] + if values and isinstance(values[0], bool): + aggregate = {"true_count": sum(values), "false_count": len(values) - sum(values)} + else: + aggregate = {"mean": sum(values) / len(values) if values else None} + result["fields"][name] = {"available_count": len(values), **aggregate} + return result + + @staticmethod + def _report(cohort, membership, folds: list[dict[str, Any]]) -> dict[str, Any]: + criteria = cohort.policy_snapshot.get("edge_vs_monetization_criteria") + edge_status = "INCOMPLETE" if isinstance(criteria, dict) and criteria else "INSUFFICIENT" + machine = { + "contract": "Cohort001-first-member-specimen-v1", + "cohort_id": str(cohort.id), + "member_ordinal": membership.ordinal, + "member_id": str(membership.id), + "strategy_version_id": str(membership.strategy_version_id), + "dataset_version_id": str(cohort.dataset_version_id), + "fold_count": len(folds), + "scenario_count_per_fold": len(SCENARIO_NAMES), + "folds": folds, + "edge_vs_monetization": {"status": edge_status, "criteria": criteria or None}, + } + return { + "machine": machine, + "human": { + "scope": ( + "Cohort001 member ordinal 1 only; Cohort002 and all other members excluded." + ), + "folds_persisted": len(folds), + "scenarios_per_fold": len(SCENARIO_NAMES), + "ledger_reconciled": all( + scenario["ledger_reconciliation"]["consistent"] + for fold in folds for scenario in fold["scenarios"] + ), + "edge_vs_monetization": edge_status, + }, + } diff --git a/control_plane/trading_studio/management/commands/tradingstudio_generate_batch01_native_acceptance_manifest.py b/control_plane/trading_studio/management/commands/tradingstudio_generate_batch01_native_acceptance_manifest.py new file mode 100644 index 0000000..2cd503a --- /dev/null +++ b/control_plane/trading_studio/management/commands/tradingstudio_generate_batch01_native_acceptance_manifest.py @@ -0,0 +1,24 @@ +"""Write the resolved Batch01 native acceptance manifest and coverage.""" + +from __future__ import annotations + +from pathlib import Path + +from django.core.management.base import BaseCommand + +from control_plane.trading_studio.indicators.batch01_native_parity import ( + write_batch01_native_acceptance_manifest, +) + + +class Command(BaseCommand): + help = "Evaluate Batch01 and write its scoped-ULP acceptance manifest." + + def add_arguments(self, parser): + parser.add_argument("--output", type=Path, required=True) + + def handle(self, *args, **options): + output = options["output"] + output.parent.mkdir(parents=True, exist_ok=True) + write_batch01_native_acceptance_manifest(output) + self.stdout.write(str(output)) diff --git a/control_plane/trading_studio/management/commands/tradingstudio_generate_batch01_native_parity_manifest.py b/control_plane/trading_studio/management/commands/tradingstudio_generate_batch01_native_parity_manifest.py new file mode 100644 index 0000000..0ced498 --- /dev/null +++ b/control_plane/trading_studio/management/commands/tradingstudio_generate_batch01_native_parity_manifest.py @@ -0,0 +1,24 @@ +"""Write the immutable local parity contract for Batch01 native evaluators.""" + +from __future__ import annotations + +from pathlib import Path + +from django.core.management.base import BaseCommand + +from control_plane.trading_studio.indicators.batch01_native_parity import ( + write_batch01_native_parity_manifest, +) + + +class Command(BaseCommand): + help = "Write the frozen Batch01 native parity manifest." + + def add_arguments(self, parser): + parser.add_argument("--output", type=Path, required=True) + + def handle(self, *args, **options): + output = options["output"] + output.parent.mkdir(parents=True, exist_ok=True) + write_batch01_native_parity_manifest(output) + self.stdout.write(str(output)) diff --git a/control_plane/trading_studio/management/commands/tradingstudio_generate_batch01_oracle_manifest.py b/control_plane/trading_studio/management/commands/tradingstudio_generate_batch01_oracle_manifest.py new file mode 100644 index 0000000..ed8aaf6 --- /dev/null +++ b/control_plane/trading_studio/management/commands/tradingstudio_generate_batch01_oracle_manifest.py @@ -0,0 +1,24 @@ +"""Write the Batch01 request manifest for an external historical oracle.""" + +from __future__ import annotations + +from pathlib import Path + +from django.core.management.base import BaseCommand + +from control_plane.trading_studio.indicators.batch01_oracle_manifest import ( + write_batch01_oracle_request_manifest, +) + + +class Command(BaseCommand): + help = "Write 97 exact Batch01 historical-oracle requests; never evaluates formulas." + + def add_arguments(self, parser): + parser.add_argument("--output", type=Path, required=True) + + def handle(self, *args, **options): + output = options["output"] + output.parent.mkdir(parents=True, exist_ok=True) + write_batch01_oracle_request_manifest(output) + self.stdout.write(str(output)) diff --git a/control_plane/trading_studio/management/commands/tradingstudio_generate_feature_catalog.py b/control_plane/trading_studio/management/commands/tradingstudio_generate_feature_catalog.py new file mode 100644 index 0000000..3ef2cd1 --- /dev/null +++ b/control_plane/trading_studio/management/commands/tradingstudio_generate_feature_catalog.py @@ -0,0 +1,42 @@ +from __future__ import annotations + +import json +from pathlib import Path + +from django.core.management.base import BaseCommand + +from control_plane.trading_studio.indicators.feature_catalog import ( + FEATURE_CATALOG_V1_PATH, + FEATURE_SAFETY_AUDIT_V1_PATH, + feature_catalog_digest, + feature_safety_audit_digest, + write_feature_artifacts, +) + + +class Command(BaseCommand): + help = "Generate deterministic FEATURE_CATALOG_V1 and FEATURE_SAFETY_AUDIT_V1 artifacts." + + def add_arguments(self, parser): + parser.add_argument("--output-dir", type=Path) + + def handle(self, *args, **options): + output_dir = options["output_dir"] + catalog_path = ( + output_dir / FEATURE_CATALOG_V1_PATH.name if output_dir else FEATURE_CATALOG_V1_PATH + ) + audit_path = ( + output_dir / FEATURE_SAFETY_AUDIT_V1_PATH.name + if output_dir + else FEATURE_SAFETY_AUDIT_V1_PATH + ) + if output_dir: + output_dir.mkdir(parents=True, exist_ok=True) + write_feature_artifacts(catalog_path, audit_path) + self.stdout.write(json.dumps({ + "catalog": str(catalog_path), + "catalog_sha256": feature_catalog_digest(), + "audit": str(audit_path), + "audit_sha256": feature_safety_audit_digest(), + "coverage": "80 validated of 1107 historical variants", + }, sort_keys=True)) diff --git a/control_plane/trading_studio/management/commands/tradingstudio_generate_oracle_windows.py b/control_plane/trading_studio/management/commands/tradingstudio_generate_oracle_windows.py new file mode 100644 index 0000000..5c388aa --- /dev/null +++ b/control_plane/trading_studio/management/commands/tradingstudio_generate_oracle_windows.py @@ -0,0 +1,70 @@ +"""Generate offline Spark input windows for an external historical oracle.""" + +from __future__ import annotations + +import json +from pathlib import Path + +from django.core.management.base import BaseCommand, CommandError + +from control_plane.trading_studio.indicators.parity_harness_v1 import parity_manifest + + +class Command(BaseCommand): + help = "Materialize deterministic offline Spark oracle windows; it never evaluates formulas." + + def add_arguments(self, parser): + parser.add_argument("--input-csv", type=Path, required=True) + parser.add_argument("--output-dir", type=Path, required=True) + parser.add_argument("--window-size", type=int, default=4096) + parser.add_argument("--spark-master", default="local[*]") + parser.add_argument("--order-column", default="timestamp") + + def handle(self, *args, **options): + if options["window_size"] <= 0: + raise CommandError("--window-size must be positive") + try: + from pyspark.sql import SparkSession, Window + from pyspark.sql.functions import col, countDistinct, row_number + except ImportError as error: + raise CommandError("pyspark is required; this command has no local fallback") from error + source = options["input_csv"] + if not source.is_file(): + raise CommandError("--input-csv must name a local file") + output_dir = options["output_dir"] + output_dir.mkdir(parents=True, exist_ok=True) + spark = ( + SparkSession.builder.master(options["spark_master"]) + .appName("artifex-oracle-windows") + .getOrCreate() + ) + try: + frame = spark.read.option("header", True).option("inferSchema", True).csv(str(source)) + order_column = options["order_column"] + if order_column not in frame.columns: + raise CommandError("--order-column must exist in --input-csv") + row_count = frame.count() + distinct_count = frame.select(countDistinct(col(order_column))).first()[0] + if row_count != distinct_count: + raise CommandError("--order-column must be unique for reproducible Spark windows") + ordered = Window.orderBy(col(order_column)) + row_index = row_number().over(ordered) - 1 + window_id = (row_index / options["window_size"]).cast("long") + windowed = frame.withColumn("oracle_window_id", window_id) + windowed.write.mode("errorifexists").parquet(str(output_dir / "windows.parquet")) + finally: + spark.stop() + (output_dir / "oracle_window_manifest_v1.json").write_text( + json.dumps( + { + **parity_manifest(), + "input_csv": str(source), + "window_size": options["window_size"], + "order_column": options["order_column"], + }, + sort_keys=True, + ) + + "\n", + encoding="utf-8", + ) + self.stdout.write(str(output_dir / "oracle_window_manifest_v1.json")) diff --git a/control_plane/trading_studio/migrations/0002_qualification_replay_v1.py b/control_plane/trading_studio/migrations/0002_qualification_replay_v1.py new file mode 100644 index 0000000..050f838 --- /dev/null +++ b/control_plane/trading_studio/migrations/0002_qualification_replay_v1.py @@ -0,0 +1,102 @@ +# Generated manually for QualificationReplayV1. + +import uuid + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [("trading_studio", "0001_initial")] + + operations = [ + migrations.CreateModel( + name="QualificationReplayRun", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, editable=False, primary_key=True, serialize=False + ), + ), + ("created_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ("fold", models.CharField(max_length=120)), + ("scenario_name", models.CharField(max_length=160)), + ("runner_name", models.CharField(max_length=160)), + ("replay_mode", models.CharField(default="CANARY_ONLY", max_length=32)), + ("input_hash", models.CharField(max_length=128)), + ("calibration", models.JSONField(default=dict)), + ("configuration", models.JSONField(default=dict)), + ("summary", models.JSONField(default=dict)), + ( + "dataset_version", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="qualification_runs", + to="trading_studio.marketdatasetversion", + ), + ), + ( + "strategy_version", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="qualification_runs", + to="trading_studio.strategyversion", + ), + ), + ], + ), + migrations.CreateModel( + name="QualificationReplayLedger", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, editable=False, primary_key=True, serialize=False + ), + ), + ("created_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ("sequence", models.PositiveIntegerField()), + ("identity", models.CharField(max_length=512)), + ("result", models.JSONField(default=dict)), + ( + "qualification_run", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="ledger_rows", + to="trading_studio.qualificationreplayrun", + ), + ), + ], + ), + migrations.AddConstraint( + model_name="qualificationreplayrun", + constraint=models.UniqueConstraint( + fields=( + "strategy_version", + "dataset_version", + "fold", + "scenario_name", + "runner_name", + "input_hash", + ), + name="unique_qualification_replay_identity", + ), + ), + migrations.AddConstraint( + model_name="qualificationreplayledger", + constraint=models.UniqueConstraint( + fields=("qualification_run", "sequence"), + name="unique_qualification_ledger_sequence", + ), + ), + migrations.AddConstraint( + model_name="qualificationreplayledger", + constraint=models.UniqueConstraint( + fields=("qualification_run", "identity"), + name="unique_qualification_ledger_identity", + ), + ), + ] diff --git a/control_plane/trading_studio/migrations/0003_cohort_membership.py b/control_plane/trading_studio/migrations/0003_cohort_membership.py new file mode 100644 index 0000000..cf45075 --- /dev/null +++ b/control_plane/trading_studio/migrations/0003_cohort_membership.py @@ -0,0 +1,31 @@ +# Generated manually for frozen cohort membership. + +import uuid + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [("trading_studio", "0002_qualification_replay_v1")] + + operations = [ + migrations.CreateModel( + name="CohortMembership", + fields=[ + ("id", models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ("created_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ("ordinal", models.PositiveIntegerField()), + ("member_id", models.UUIDField(unique=True)), + ("provenance", models.CharField(max_length=80)), + ("metadata", models.JSONField(default=dict)), + ("cohort", models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name="memberships", to="trading_studio.tradingcohort")), + ("strategy_version", models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name="cohort_memberships", to="trading_studio.strategyversion")), + ], + ), + migrations.AddConstraint( + model_name="cohortmembership", + constraint=models.UniqueConstraint(fields=("cohort", "ordinal"), name="unique_cohort_member_ordinal"), + ), + ] diff --git a/control_plane/trading_studio/models.py b/control_plane/trading_studio/models.py index a8907bd..eb44769 100644 --- a/control_plane/trading_studio/models.py +++ b/control_plane/trading_studio/models.py @@ -237,6 +237,28 @@ class TradingCohort(TimestampedModel): report = models.ForeignKey("TradingResearchReport", on_delete=models.SET_NULL, null=True, blank=True, related_name="cohorts") +class CohortMembership(TimestampedModel): + """An ordered, immutable strategy membership imported from a frozen cohort spec.""" + + cohort = models.ForeignKey(TradingCohort, on_delete=models.CASCADE, related_name="memberships") + strategy_version = models.ForeignKey(StrategyVersion, on_delete=models.PROTECT, related_name="cohort_memberships") + ordinal = models.PositiveIntegerField() + member_id = models.UUIDField(unique=True) + provenance = models.CharField(max_length=80) + metadata = models.JSONField(default=dict) + + class Meta: + constraints = [models.UniqueConstraint(fields=["cohort", "ordinal"], name="unique_cohort_member_ordinal")] + + def save(self, *args, **kwargs): + if self.pk and type(self).objects.filter(pk=self.pk).exists(): + original = type(self).objects.get(pk=self.pk) + fields = ["cohort_id", "strategy_version_id", "ordinal", "member_id", "provenance", "metadata"] + if any(getattr(self, field) != getattr(original, field) for field in fields): + raise ValueError("CohortMembership is immutable after frozen-spec materialization.") + super().save(*args, **kwargs) + + class StrategyExperiment(TimestampedModel): cohort = models.ForeignKey(TradingCohort, on_delete=models.CASCADE, related_name="experiments") strategy_version = models.ForeignKey(StrategyVersion, on_delete=models.PROTECT, related_name="experiments") @@ -266,6 +288,42 @@ class BacktestRun(TimestampedModel): failure_details = models.TextField(blank=True) +class QualificationReplayRun(TimestampedModel): + """Persisted CANARY_ONLY qualification replay and its immutable inputs.""" + + strategy_version = models.ForeignKey(StrategyVersion, on_delete=models.PROTECT, related_name="qualification_runs") + dataset_version = models.ForeignKey(MarketDatasetVersion, on_delete=models.PROTECT, related_name="qualification_runs") + fold = models.CharField(max_length=120) + scenario_name = models.CharField(max_length=160) + runner_name = models.CharField(max_length=160) + replay_mode = models.CharField(max_length=32, default="CANARY_ONLY") + input_hash = models.CharField(max_length=128) + calibration = models.JSONField(default=dict) + configuration = models.JSONField(default=dict) + summary = models.JSONField(default=dict) + + class Meta: + constraints = [models.UniqueConstraint( + fields=["strategy_version", "dataset_version", "fold", "scenario_name", "runner_name", "input_hash"], + name="unique_qualification_replay_identity", + )] + + +class QualificationReplayLedger(TimestampedModel): + """Append-only replay result. Payload preserves every directly emitted ledger field.""" + + qualification_run = models.ForeignKey(QualificationReplayRun, on_delete=models.CASCADE, related_name="ledger_rows") + sequence = models.PositiveIntegerField() + identity = models.CharField(max_length=512) + result = models.JSONField(default=dict) + + class Meta: + constraints = [ + models.UniqueConstraint(fields=["qualification_run", "sequence"], name="unique_qualification_ledger_sequence"), + models.UniqueConstraint(fields=["qualification_run", "identity"], name="unique_qualification_ledger_identity"), + ] + + class WalkForwardRun(TimestampedModel): experiment = models.ForeignKey(StrategyExperiment, on_delete=models.PROTECT, related_name="walk_forwards") dataset_version = models.ForeignKey(MarketDatasetVersion, on_delete=models.PROTECT, related_name="walk_forward_runs") diff --git a/control_plane/trading_studio/qualification.py b/control_plane/trading_studio/qualification.py new file mode 100644 index 0000000..eed3002 --- /dev/null +++ b/control_plane/trading_studio/qualification.py @@ -0,0 +1,684 @@ +"""Deterministic QualificationReplayV1 with no external or reference-data dependency.""" + +from __future__ import annotations + +from collections.abc import Iterable +from dataclasses import asdict, dataclass +from datetime import datetime +from enum import StrEnum +from hashlib import sha256 +from json import dumps + + +class ReplayMode(StrEnum): + CANARY_ONLY = "CANARY_ONLY" + + +class CalibrationMethod(StrEnum): + RAW = "RAW" + PERCENTILE = "PERCENTILE" + + +class SameBarPolicy(StrEnum): + PESSIMISTIC_SL = "PESSIMISTIC_SL" + + +class EventType(StrEnum): + SIGNAL = "SIGNAL" + ENTRY_QUEUED = "ENTRY_QUEUED" + ENTRY = "ENTRY" + EXIT = "EXIT" + COOLDOWN_START = "COOLDOWN_START" + COOLDOWN_END = "COOLDOWN_END" + ENTRY_SKIPPED = "ENTRY_SKIPPED" + + +class ReplayState(StrEnum): + FLAT = "FLAT" + ENTRY_QUEUED = "ENTRY_QUEUED" + OPEN = "OPEN" + COOLDOWN = "COOLDOWN" + + +@dataclass(frozen=True) +class CostModel: + version: str + entry_commission_bps: float = 0.0 + exit_commission_bps: float = 0.0 + entry_slippage_bps: float = 0.0 + exit_slippage_bps: float = 0.0 + funding_bps_per_bar: float = 0.0 + entry_other_cost: float = 0.0 + exit_other_cost: float = 0.0 + + def __post_init__(self) -> None: + if not self.version: + raise ValueError("Cost model version is required.") + if ( + min( + self.entry_commission_bps, + self.exit_commission_bps, + self.entry_slippage_bps, + self.exit_slippage_bps, + self.entry_other_cost, + self.exit_other_cost, + ) + < 0 + ): + raise ValueError("Commission, slippage, and other costs cannot be negative.") + + @property + def nominal_round_trip_bps(self) -> float: + """Known entry/exit friction, excluding time-dependent funding and fixed costs.""" + return ( + self.entry_commission_bps + + self.exit_commission_bps + + self.entry_slippage_bps + + self.exit_slippage_bps + ) + + +@dataclass(frozen=True) +class ScenarioSpec: + name: str + stop_loss_bps: float + take_profit_bps: float + entry_delay_bars: int = 1 + cooldown_bars: int = 0 + max_holding_bars: int = 1 + allow_weekend_entries: bool = False + same_bar_policy: SameBarPolicy = SameBarPolicy.PESSIMISTIC_SL + cost_model: CostModel = CostModel(version="qualification-v1") + + def __post_init__(self) -> None: + if not self.name: + raise ValueError("Every qualification scenario must be named.") + if min(self.stop_loss_bps, self.take_profit_bps) <= 0: + raise ValueError("TP and SL widths must be positive.") + if self.entry_delay_bars < 1 or self.cooldown_bars < 0 or self.max_holding_bars < 1: + raise ValueError("Invalid entry delay, cooldown, or holding period.") + + +def qualification_scenario_catalog() -> dict[str, ScenarioSpec]: + """The fixed, named QualificationReplayV1 scenario catalog.""" + + def total_cost(name: str, total_bps: float) -> ScenarioSpec: + component = total_bps / 4 + return ScenarioSpec( + name, + 100, + 100, + cost_model=CostModel( + version=f"{name.lower()}-v1", + entry_commission_bps=component, + exit_commission_bps=component, + entry_slippage_bps=component, + exit_slippage_bps=component, + ), + ) + + baseline = ScenarioSpec("BASELINE", 100, 100) + return { + "BASELINE": baseline, + "SLIPPAGE_ADVERSE_2BP": ScenarioSpec( + "SLIPPAGE_ADVERSE_2BP", + 100, + 100, + cost_model=CostModel( + version="slippage-adverse-2bp-v1", + entry_slippage_bps=1, + exit_slippage_bps=1, + ), + ), + "TOTAL_COST_6BP": total_cost("TOTAL_COST_6BP", 6), + "TOTAL_COST_10BP": total_cost("TOTAL_COST_10BP", 10), + "TOTAL_COST_15BP": total_cost("TOTAL_COST_15BP", 15), + "PESSIMISTIC_SAME_BAR": ScenarioSpec("PESSIMISTIC_SAME_BAR", 100, 100), + "ENTRY_DELAY_PLUS_ONE_BAR": ScenarioSpec( + "ENTRY_DELAY_PLUS_ONE_BAR", 100, 100, entry_delay_bars=2 + ), + "WEEKDAYS_ONLY": ScenarioSpec("WEEKDAYS_ONLY", 100, 100, allow_weekend_entries=False), + "ALL_DAYS": ScenarioSpec("ALL_DAYS", 100, 100, allow_weekend_entries=True), + "STOP_WIDTH_100": ScenarioSpec("STOP_WIDTH_100", 100, 100), + "STOP_WIDTH_75": ScenarioSpec("STOP_WIDTH_75", 75, 100), + "STOP_WIDTH_50": ScenarioSpec("STOP_WIDTH_50", 50, 100), + "STOP_WIDTH_25": ScenarioSpec("STOP_WIDTH_25", 25, 100), + } + + +@dataclass(frozen=True) +class Bar: + at: datetime + open: float + high: float + low: float + close: float + signal: float | None = None + context: tuple[float, ...] = () + reference: str = "" + + def __post_init__(self) -> None: + if min(self.open, self.high, self.low, self.close) <= 0: + raise ValueError("OHLC prices must be positive.") + if self.high < max(self.open, self.close) or self.low > min(self.open, self.close): + raise ValueError("OHLC values are inconsistent.") + + +@dataclass(frozen=True) +class Calibration: + method: CalibrationMethod + threshold: float + percentile: float | None + source_record_ids: tuple[str, ...] + source_combo: str + fold: str + input_hash: str + train_start: datetime + train_end: datetime + sample_count: int + + +@dataclass(frozen=True) +class ReplayEvent: + sequence: int + event_type: EventType + state: ReplayState + at: datetime + bar_index: int + detail: str = "" + + +@dataclass(frozen=True) +class DEQPrimitives: + return_1_bars_bps: float | None + return_2_bars_bps: float | None + return_3_bars_bps: float | None + return_5_bars_bps: float | None + return_10_bars_bps: float | None + mfe_bps: float + mae_bps: float + time_to_positive_bars: int | None + time_to_25_bps_bars: int | None + time_to_50_bps_bars: int | None + max_adverse_before_positive_bps: float + winner_negative_first: bool + recovery_bars: int | None + + +@dataclass(frozen=True) +class RescuePrimitives: + activated: bool + trigger_drawdown: float + max_drawdown: float + max_drawdown_bps: float + peak_equity: float + final_equity: float + trade_count: int + win_count: int + loss_count: int + win_rate: float + gross_profit: float + gross_loss: float + profit_factor: float | None + gross_pnl: float + commissions: float + slippage: float + funding: float + other_cost: float + net_pnl: float + average_trade_pnl: float + max_losing_streak: int + recovered: bool + recovery_bars: int | None + + +RescueMetrics = RescuePrimitives + + +@dataclass(frozen=True) +class LedgerRow: + identity: str + strategy: str + dataset: str + fold: str + scenario: str + runner: str + signal_at: datetime + signal_bar: int + signal_reference: str + entry_at: datetime + entry_bar: int + entry_reference_price: float + entry_execution_price: float + exit_at: datetime + exit_bar: int + exit_reference_price: float + exit_execution_price: float + take_profit_price: float + stop_loss_price: float + quantity: float + gross_pnl: float + entry_commission: float + exit_commission: float + entry_slippage: float + exit_slippage: float + funding: float + other_cost: float + net_pnl: float + holding_bars: int + cooldown_bars: int + same_bar_policy: SameBarPolicy + exit_reason: str + deq: DEQPrimitives + + +@dataclass(frozen=True) +class ReplayAggregate: + mode: ReplayMode + strategy: str + dataset: str + fold: str + scenario: ScenarioSpec + runner: str + calibration: Calibration + events: tuple[ReplayEvent, ...] + ledger: tuple[LedgerRow, ...] + gross_pnl: float + commissions: float + slippage: float + funding: float + other_cost: float + net_pnl: float + rescue: RescueMetrics + + +def calibrate_train_only( + bars: Iterable[Bar], + *, + method: CalibrationMethod, + fold: str, + train_start: datetime, + train_end: datetime, + source_record_ids: Iterable[str], + source_combo: str, + percentile: float | None = None, + allow_empty_raw: bool = False, +) -> Calibration: + """Calibrate from continuous signal/context records strictly inside the train window.""" + records = tuple(bars) + train_records = [bar for bar in records if train_start <= bar.at < train_end] + train = [bar for bar in records if train_start <= bar.at < train_end and bar.signal is not None] + source_ids = tuple(source_record_ids) + raw_empty_allowed = method is CalibrationMethod.RAW and allow_empty_raw + if ( + not train_records + or (not train and not raw_empty_allowed) + or not source_ids + or not fold + or not source_combo + ): + raise ValueError( + "Train-only calibration requires train records, sources, fold, and source combo." + ) + values = sorted(abs(bar.signal) for bar in train if bar.signal is not None) + if method is CalibrationMethod.RAW: + threshold = sum(values) / len(values) if values else 0.0 + selected_percentile = None + else: + if percentile is None or not 0 <= percentile <= 100: + raise ValueError("PERCENTILE calibration requires a percentile from 0 through 100.") + position = round((len(values) - 1) * percentile / 100) + threshold = values[position] + selected_percentile = percentile + payload = [ + { + "at": bar.at.isoformat(), + "signal": bar.signal, + "context": bar.context, + "reference": bar.reference, + } + for bar in (train_records if raw_empty_allowed else train) + ] + input_hash = sha256(dumps(payload, sort_keys=True, separators=(",", ":")).encode()).hexdigest() + return Calibration( + method, + threshold, + selected_percentile, + source_ids, + source_combo, + fold, + input_hash, + train_start, + train_end, + len(train), + ) + + +class QualificationReplayV1: + mode = ReplayMode.CANARY_ONLY + + def run( + self, + bars: Iterable[Bar], + *, + strategy: str, + dataset: str, + fold: str, + scenario: ScenarioSpec, + runner: str, + calibration: Calibration, + initial_equity: float = 1.0, + ) -> ReplayAggregate: + sequence = tuple(bars) + if not strategy or not dataset or not fold or not runner: + raise ValueError("Strategy, dataset, fold, and runner are required.") + if calibration.fold != fold or initial_equity <= 0: + raise ValueError("Calibration fold must match and initial equity must be positive.") + if any(left.at >= right.at for left, right in zip(sequence, sequence[1:], strict=False)): + raise ValueError("Bars must be strictly chronological.") + + events: list[ReplayEvent] = [] + ledger: list[LedgerRow] = [] + state = ReplayState.FLAT + queued: tuple[Bar, int] | None = None + position: tuple[Bar, int, float, float, float] | None = None + cooldown_remaining = 0 + + def emit( + event_type: EventType, state_value: ReplayState, index: int, detail: str = "" + ) -> None: + events.append( + ReplayEvent(len(events), event_type, state_value, sequence[index].at, index, detail) + ) + + for index, bar in enumerate(sequence): + if state is ReplayState.COOLDOWN: + cooldown_remaining -= 1 + if cooldown_remaining == 0: + state = ReplayState.FLAT + emit(EventType.COOLDOWN_END, state, index) + else: + continue + + if state is ReplayState.ENTRY_QUEUED and queued is not None and index == queued[1]: + signal_bar, _ = queued + if not scenario.allow_weekend_entries and bar.at.weekday() >= 5: + emit(EventType.ENTRY_SKIPPED, ReplayState.FLAT, index, "weekend") + queued = None + state = ReplayState.FLAT + else: + direction = 1 if signal_bar.signal and signal_bar.signal > 0 else -1 + entry_reference = bar.open + entry_execution = self._apply_slippage( + entry_reference, direction, scenario.cost_model.entry_slippage_bps + ) + stop = entry_execution * (1 - direction * scenario.stop_loss_bps / 10_000) + target = entry_execution * (1 + direction * scenario.take_profit_bps / 10_000) + position = (signal_bar, index, entry_execution, stop, target) + queued = None + state = ReplayState.OPEN + emit(EventType.ENTRY, state, index) + + if state is ReplayState.OPEN and position is not None: + signal_bar, entry_index, entry_execution, stop, target = position + exit_reason, exit_reference = self._exit_for_bar( + bar, entry_execution, stop, target, index - entry_index + 1, scenario + ) + if exit_reason: + direction = 1 if signal_bar.signal and signal_bar.signal > 0 else -1 + row = self._ledger_row( + sequence, + strategy, + dataset, + fold, + scenario, + runner, + signal_bar, + entry_index, + index, + entry_execution, + stop, + target, + exit_reference, + direction, + ) + ledger.append(row) + emit(EventType.EXIT, ReplayState.FLAT, index, exit_reason) + position = None + if scenario.cooldown_bars: + state = ReplayState.COOLDOWN + cooldown_remaining = scenario.cooldown_bars + emit(EventType.COOLDOWN_START, state, index) + else: + state = ReplayState.FLAT + + if ( + state is ReplayState.FLAT + and bar.at >= calibration.train_end + and bar.signal is not None + ): + if abs( + bar.signal + ) >= calibration.threshold and index + scenario.entry_delay_bars < len(sequence): + emit(EventType.SIGNAL, state, index) + queued = (bar, index + scenario.entry_delay_bars) + state = ReplayState.ENTRY_QUEUED + emit(EventType.ENTRY_QUEUED, state, index, f"bar={queued[1]}") + + commissions = sum(row.entry_commission + row.exit_commission for row in ledger) + slippage = sum(row.entry_slippage + row.exit_slippage for row in ledger) + funding = sum(row.funding for row in ledger) + other = sum(row.other_cost for row in ledger) + gross = sum(row.gross_pnl for row in ledger) + net = sum(row.net_pnl for row in ledger) + rescue = self._rescue(tuple(ledger), initial_equity) + return ReplayAggregate( + self.mode, + strategy, + dataset, + fold, + scenario, + runner, + calibration, + tuple(events), + tuple(ledger), + gross, + commissions, + slippage, + funding, + other, + net, + rescue, + ) + + @staticmethod + def _apply_slippage(price: float, direction: int, bps: float) -> float: + return price * (1 + direction * bps / 10_000) + + @staticmethod + def _exit_for_bar( + bar: Bar, entry: float, stop: float, target: float, held: int, scenario: ScenarioSpec + ) -> tuple[str, float]: + long = target > entry + stopped = bar.low <= stop if long else bar.high >= stop + target_hit = bar.high >= target if long else bar.low <= target + if stopped and (scenario.same_bar_policy is SameBarPolicy.PESSIMISTIC_SL or not target_hit): + return "SL", min(bar.open, stop) if long else max(bar.open, stop) + if target_hit: + return "TP", target + if held >= scenario.max_holding_bars: + return "TIME", bar.close + return "", 0.0 + + def _ledger_row( + self, + bars: tuple[Bar, ...], + strategy: str, + dataset: str, + fold: str, + scenario: ScenarioSpec, + runner: str, + signal: Bar, + entry_index: int, + exit_index: int, + entry: float, + stop: float, + target: float, + exit_reference: float, + direction: int, + ) -> LedgerRow: + cost = scenario.cost_model + exit_execution = self._apply_slippage(exit_reference, -direction, cost.exit_slippage_bps) + entry_commission = entry * cost.entry_commission_bps / 10_000 + exit_commission = exit_execution * cost.exit_commission_bps / 10_000 + entry_slippage = abs(entry - bars[entry_index].open) + exit_slippage = abs(exit_execution - exit_reference) + holding = exit_index - entry_index + 1 + funding = entry * holding * cost.funding_bps_per_bar / 10_000 + other = cost.entry_other_cost + cost.exit_other_cost + gross = (exit_execution - entry) * direction + net = gross - entry_commission - exit_commission - funding - other + deq = self._deq(bars, entry_index, entry, direction) + identity = f"{strategy}:{dataset}:{fold}:{scenario.name}:{runner}:{signal.at.isoformat()}" + return LedgerRow( + identity, + strategy, + dataset, + fold, + scenario.name, + runner, + signal.at, + bars.index(signal), + signal.reference, + bars[entry_index].at, + entry_index, + bars[entry_index].open, + entry, + bars[exit_index].at, + exit_index, + exit_reference, + exit_execution, + target, + stop, + 1.0, + gross, + entry_commission, + exit_commission, + entry_slippage, + exit_slippage, + funding, + other, + net, + holding, + scenario.cooldown_bars, + scenario.same_bar_policy, + self._exit_for_bar(bars[exit_index], entry, stop, target, holding, scenario)[0], + deq, + ) + + @staticmethod + def _deq( + bars: tuple[Bar, ...], + entry_index: int, + entry: float, + direction: int, + ) -> DEQPrimitives: + path = bars[entry_index:] + highs = [direction * (bar.high - entry) / entry * 10_000 for bar in path] + lows = [direction * (bar.low - entry) / entry * 10_000 for bar in path] + favorable = highs if direction > 0 else lows + adverse = lows if direction > 0 else highs + positive_at = next((index for index, value in enumerate(favorable) if value > 0), None) + before_positive = adverse[:positive_at] if positive_at is not None else adverse + recovery = next( + (index for index, bar in enumerate(path) if direction * (bar.close - entry) >= 0), None + ) + + def forward(horizon: int) -> float | None: + if entry_index + horizon >= len(bars): + return None + return direction * (bars[entry_index + horizon].close - entry) / entry * 10_000 + + return DEQPrimitives( + forward(1), + forward(2), + forward(3), + forward(5), + forward(10), + max(favorable), + min(adverse), + positive_at, + next((index for index, value in enumerate(favorable) if value >= 25), None), + next((index for index, value in enumerate(favorable) if value >= 50), None), + min(before_positive, default=0.0), + path[-1].close * direction > entry * direction and min(adverse) < 0, + recovery, + ) + + @staticmethod + def _rescue(ledger: tuple[LedgerRow, ...], initial_equity: float) -> RescuePrimitives: + equity = initial_equity + peak = equity + max_drawdown = 0.0 + max_losing_streak = losing_streak = 0 + recovery_bars: int | None = 0 + recovery_target = initial_equity + gross_profit = gross_loss = 0.0 + for index, row in enumerate(ledger, start=1): + equity += row.net_pnl + gross_profit += max(row.net_pnl, 0) + gross_loss += min(row.net_pnl, 0) + losing_streak = losing_streak + 1 if row.net_pnl < 0 else 0 + max_losing_streak = max(max_losing_streak, losing_streak) + peak = max(peak, equity) + drawdown = peak - equity + if drawdown > max_drawdown: + max_drawdown = drawdown + recovery_target = peak + recovery_bars = None + elif recovery_bars is None and equity >= recovery_target: + recovery_bars = index + wins = sum(row.net_pnl > 0 for row in ledger) + losses = sum(row.net_pnl < 0 for row in ledger) + commissions = sum(row.entry_commission + row.exit_commission for row in ledger) + slippage = sum(row.entry_slippage + row.exit_slippage for row in ledger) + funding = sum(row.funding for row in ledger) + other_cost = sum(row.other_cost for row in ledger) + gross_pnl = sum(row.gross_pnl for row in ledger) + net_pnl = sum(row.net_pnl for row in ledger) + return RescuePrimitives( + activated=equity <= 0, + trigger_drawdown=initial_equity, + max_drawdown=max_drawdown, + max_drawdown_bps=max_drawdown / initial_equity * 10_000, + peak_equity=peak, + final_equity=equity, + trade_count=len(ledger), + win_count=wins, + loss_count=losses, + win_rate=wins / len(ledger) if ledger else 0, + gross_profit=gross_profit, + gross_loss=gross_loss, + profit_factor=gross_profit / abs(gross_loss) if gross_loss else None, + gross_pnl=gross_pnl, + commissions=commissions, + slippage=slippage, + funding=funding, + other_cost=other_cost, + net_pnl=net_pnl, + average_trade_pnl=net_pnl / len(ledger) if ledger else 0.0, + max_losing_streak=max_losing_streak, + recovered=recovery_bars is not None, + recovery_bars=recovery_bars, + ) + + +def ledger_payload(row: LedgerRow) -> dict[str, object]: + """JSON-safe immutable representation for the Django ledger model.""" + return asdict( + row, + dict_factory=lambda values: { + key: value.isoformat() if isinstance(value, datetime) else value + for key, value in values + }, + ) diff --git a/control_plane/trading_studio/services.py b/control_plane/trading_studio/services.py index f77a8dc..3a79719 100644 --- a/control_plane/trading_studio/services.py +++ b/control_plane/trading_studio/services.py @@ -2,6 +2,7 @@ from __future__ import annotations import hashlib import json +from dataclasses import asdict from datetime import datetime from decimal import Decimal from typing import Any @@ -14,11 +15,12 @@ from control_plane.trading_studio.models import ( AllocationTier, BacktestRun, DataKind, EvidenceStatus, ExperimentStatus, FailureType, FeatureDefinition, FeatureSetVersion, LiveStrategyRun, MarketDataset, MarketDatasetVersion, RunStatus, ShadowRun, SplitKind, - Strategy, StrategyCapitalAllocation, StrategyEvaluation, StrategyExperiment, + QualificationReplayLedger, QualificationReplayRun, Strategy, StrategyCapitalAllocation, StrategyEvaluation, StrategyExperiment, StrategyPromotionDecision, StrategyStage, StrategyVersion, TradingCohort, TradingProject, TradingProjectStatus, TradingResearchReport, ) from control_plane.trading_studio.profiles import CryptoTradingProfile, ExistingSystemProfile, HyperScalperProfile, TradingProjectProfile +from control_plane.trading_studio.qualification import Bar, Calibration, QualificationReplayV1, ScenarioSpec, ledger_payload class TradingStudioService: @@ -125,6 +127,71 @@ class TradingStudioService: version.save(update_fields=["holdout_exposure_count", "immutable", "updated_at"]) return run + @transaction.atomic + def run_qualification_canary( + self, *, strategy_version: StrategyVersion, dataset_version: MarketDatasetVersion, fold: str, + scenario: ScenarioSpec, runner_name: str, bars: list[Bar], calibration: Calibration, + protocol_identity: dict[str, Any] | None = None, + require_protocol_identity: bool = False, + ) -> QualificationReplayRun: + """Persist a supplied Cohort001 replay; never synthesize unavailable canary records.""" + missing = [ + name + for name, value in ( + ("strategy_version", strategy_version), + ("dataset_version", dataset_version), + ("fold", fold), + ("bars", bars), + ("calibration", calibration), + ) + if not value + ] + if missing: + raise ValueError( + "CANARY_ONLY refuses to run: missing materialized " + ", ".join(missing) + "." + ) + result = QualificationReplayV1().run( + bars, strategy=str(strategy_version.id), dataset=str(dataset_version.id), fold=fold, + scenario=scenario, runner=runner_name, calibration=calibration, + ) + configuration = self.qualification_configuration( + scenario, + protocol_identity=protocol_identity, + require_protocol_identity=require_protocol_identity, + ) + run = QualificationReplayRun.objects.create( + strategy_version=strategy_version, dataset_version=dataset_version, fold=fold, + scenario_name=scenario.name, runner_name=runner_name, replay_mode=result.mode, + input_hash=calibration.input_hash, calibration=self._json_safe(asdict(calibration)), + configuration=configuration, summary={ + "gross_pnl": result.gross_pnl, "net_pnl": result.net_pnl, "event_count": len(result.events), + "ledger_count": len(result.ledger), "rescue": self._json_safe(asdict(result.rescue)), + }, + ) + QualificationReplayLedger.objects.bulk_create([ + QualificationReplayLedger(qualification_run=run, sequence=index, identity=row.identity, + result=self._json_safe(ledger_payload(row))) + for index, row in enumerate(result.ledger) + ]) + return run + + @staticmethod + def qualification_configuration( + scenario: ScenarioSpec, + *, + protocol_identity: dict[str, Any] | None = None, + require_protocol_identity: bool = False, + ) -> dict[str, Any]: + """Build the immutable scenario snapshot used for persisted replay identity.""" + if require_protocol_identity and not protocol_identity: + raise ValueError("Batch qualification requires a protocol identity snapshot.") + configuration = TradingStudioService._json_safe(asdict(scenario)) + if protocol_identity is not None: + if not isinstance(protocol_identity, dict) or not protocol_identity: + raise ValueError("Protocol identity must be a non-empty object.") + configuration["protocol_identity"] = TradingStudioService._json_safe(protocol_identity) + return configuration + def judge_backtest(self, experiment: StrategyExperiment, backtest: BacktestRun, *, policy: dict[str, Any]) -> StrategyEvaluation: metrics = backtest.metrics failure = "" @@ -187,3 +254,13 @@ class TradingStudioService: @staticmethod def _hash(value: Any) -> str: return hashlib.sha256(json.dumps(value, sort_keys=True, default=str).encode()).hexdigest() + + @staticmethod + def _json_safe(value: Any) -> Any: + if isinstance(value, datetime): + return value.isoformat() + if isinstance(value, dict): + return {key: TradingStudioService._json_safe(item) for key, item in value.items()} + if isinstance(value, (list, tuple)): + return [TradingStudioService._json_safe(item) for item in value] + return value diff --git a/generate_full_historical_oracle_request.py b/generate_full_historical_oracle_request.py new file mode 100644 index 0000000..7701fe9 --- /dev/null +++ b/generate_full_historical_oracle_request.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +"""Build the exact 711-feature code-5056feb oracle request without Django.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +from pathlib import Path + +ENGINE_REVISION = "code-5056feb" +INPUT_COLUMNS = ["close", "high", "low", "volume"] + + +def canonical(value: object) -> bytes: + return json.dumps(value, sort_keys=True, separators=(",", ":"), allow_nan=False).encode("utf-8") + + +def sha256(path: Path) -> str: + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def validate_usage_summary(path: Path) -> None: + payload = json.loads(path.read_text(encoding="utf-8")) + if payload.get("artifact") != "HISTORICAL_FEATURE_USAGE_SUMMARY_V1": + raise ValueError("--usage-summary is not HISTORICAL_FEATURE_USAGE_SUMMARY_V1") + if payload.get("counts", {}).get("role_independent_primitives") != 711: + raise ValueError("usage summary does not attest to 711 role-independent primitives") + + +def triples_from_engineering(path: Path) -> set[tuple[int, int, float]]: + payload = json.loads(path.read_text(encoding="utf-8")) + if payload.get("artifact") != "ENGINEERING_FAMILY_MAP_V1": + raise ValueError("--engineering-map is not ENGINEERING_FAMILY_MAP_V1") + return { + (int(row["indicator_id"]), int(row["period"]), float(row["p1"])) + for row in payload["primitives"] + } + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--usage-summary", type=Path, required=True, help="historical_feature_usage_v1_summary.json") + parser.add_argument("--engineering-map", type=Path, required=True, help="engineering_family_map_v1.json") + parser.add_argument("--input-csv", type=Path, required=True) + parser.add_argument("--output", type=Path, required=True) + parser.add_argument("--deq-targets", type=Path, help="optional JSON metadata copied into the request") + args = parser.parse_args() + + validate_usage_summary(args.usage_summary) + engineering = triples_from_engineering(args.engineering_map) + if len(engineering) != 711: + raise ValueError(f"engineering map contains {len(engineering)} rather than 711 primitives") + if not args.input_csv.is_file(): + raise ValueError("--input-csv must be a file") + semantic_base = { + "engine_revision": ENGINE_REVISION, + "input_columns": INPUT_COLUMNS, + "output_dtype": "float64", + "window_policy": "continuous_full_history", + } + requests = [] + for indicator_id, period, p1 in sorted(engineering): + semantic = {**semantic_base, "indicator_id": indicator_id, "period": period, "p1": p1} + requests.append( + { + "request_id": f"hs22_{indicator_id}_{period}_{p1:g}", + "indicator_id": indicator_id, + "period": period, + "p1": p1, + "semantic_fingerprint": hashlib.sha256(canonical(semantic)).hexdigest(), + } + ) + payload: dict[str, object] = { + "schema_version": 1, + "artifact": "HISTORICAL_FEATURE_ORACLE_V1_REQUEST", + **semantic_base, + "input_csv_sha256": sha256(args.input_csv), + "source_artifacts": { + "usage_summary": {"path": args.usage_summary.name, "sha256": sha256(args.usage_summary)}, + "engineering_map": {"path": args.engineering_map.name, "sha256": sha256(args.engineering_map)}, + }, + "requests": requests, + } + if args.deq_targets: + payload["deq_targets"] = json.loads(args.deq_targets.read_text(encoding="utf-8")) + payload["source_artifacts"]["deq_targets"] = {"path": args.deq_targets.name, "sha256": sha256(args.deq_targets)} + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_bytes(canonical(payload) + b"\n") + print(args.output) + + +if __name__ == "__main__": + main() diff --git a/historical_feature_oracle_v1.py b/historical_feature_oracle_v1.py new file mode 100644 index 0000000..35adbbe --- /dev/null +++ b/historical_feature_oracle_v1.py @@ -0,0 +1,214 @@ +"""Standalone runner for recovered historical ``hyperscalper.fast_engine``. + +This file intentionally has no Artifex imports. Copy it with a request JSON, +CSV, and the recovered ``code-5056feb/src`` tree to run an external oracle. +""" + +from __future__ import annotations + +import argparse +import hashlib +import importlib +import json +import sys +from pathlib import Path +from typing import Any + +import numpy as np + +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_engine(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") + sys.path.insert(0, str(source)) + engine = importlib.import_module("hyperscalper.fast_engine") + if Path(engine.__file__).resolve() != engine_file.resolve(): + raise RuntimeError("refused a hyperscalper.fast_engine outside --recovered-source") + return engine + + +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) + engine = _load_engine(recovered_source) + requests = _requests(payload, {int(row[0]) for row in engine.FAST_POOL}) + windows = _windows(payload, len(close)) + outputs: dict[str, np.ndarray] = {} + records = [] + for row in requests: + values = np.asarray( + engine.compute( + row["indicator_id"], close, high, low, volume, row["period"], row["p1"] + ), + dtype=np.float64, + ) + # Validate the artifact against a second direct call to the recovered dispatcher. + direct = np.asarray( + engine.compute( + 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 compute 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() + ), + "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() diff --git a/pyproject.toml b/pyproject.toml index 74e5f94..42451e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,10 +8,13 @@ dependencies = [ "psycopg[binary]>=3.2,<4.0", "langgraph>=0.2,<0.3", "structlog>=24.4,<25.0", + "numpy>=2.0,<3.0", + "numba>=0.60,<1.0", ] [project.optional-dependencies] dev = [ + "pyarrow>=25.0.1", "pytest>=8.3,<9.0", "pytest-django>=4.9,<5.0", "ruff>=0.8,<1.0", diff --git a/run_historical_oracle_overnight.py b/run_historical_oracle_overnight.py new file mode 100644 index 0000000..3680611 --- /dev/null +++ b/run_historical_oracle_overnight.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python3 +"""Resumable, Django-free full-history oracle runner for recovered code-5056feb.""" + +from __future__ import annotations + +import argparse +import hashlib +import importlib +import json +import os +import sys +import time +from datetime import datetime, timezone +from pathlib import Path +from typing import Any + +import numpy as np + +ENGINE_REVISION = "code-5056feb" +REQUIRED_COLUMNS = ("close", "high", "low", "volume") + + +def canonical(value: object) -> bytes: + return json.dumps(value, sort_keys=True, separators=(",", ":"), allow_nan=False).encode("utf-8") + + +def digest_bytes(value: bytes) -> str: + return hashlib.sha256(value).hexdigest() + + +def digest_file(path: Path) -> str: + return digest_bytes(path.read_bytes()) + + +def array_digest(values: np.ndarray) -> str: + values = np.ascontiguousarray(values) + return digest_bytes(canonical({"dtype": values.dtype.str, "shape": values.shape}) + b"\0" + values.tobytes()) + + +def atomic_bytes(path: Path, data: bytes) -> None: + temporary = path.with_suffix(path.suffix + ".tmp") + temporary.write_bytes(data) + os.replace(temporary, path) + + +def now() -> str: + return datetime.now(timezone.utc).isoformat() + + +def log(path: Path, event: str, **fields: object) -> None: + atomic_append = canonical({"at": now(), "event": event, **fields}) + b"\n" + with path.open("ab") as handle: + handle.write(atomic_append) + handle.flush() + os.fsync(handle.fileno()) + + +def load_engine(source: Path): + engine_file = source / "hyperscalper" / "fast_engine.py" + if not engine_file.is_file() or not (source / "hyperscalper" / "__init__.py").is_file(): + raise ValueError("--recovered-source must contain hyperscalper/fast_engine.py") + sys.path.insert(0, str(source)) + engine = importlib.import_module("hyperscalper.fast_engine") + if Path(engine.__file__).resolve() != engine_file.resolve(): + raise RuntimeError("refused a fast_engine outside --recovered-source") + return engine + + +def load_csv(path: Path) -> tuple[np.ndarray, ...]: + table = np.atleast_1d(np.genfromtxt(path, delimiter=",", names=True, dtype=None, encoding="utf-8")) + names = set(table.dtype.names or ()) + if set(REQUIRED_COLUMNS) - names: + raise ValueError("CSV must contain close, high, low, volume") + arrays = tuple(np.asarray(table[name], dtype=np.float64) for name in REQUIRED_COLUMNS) + if not arrays[0].size or any(values.shape != arrays[0].shape for values in arrays): + raise ValueError("CSV OHLCV columns must be non-empty, equal-length vectors") + return arrays + + +def load_request(path: Path, engine: Any) -> list[dict[str, Any]]: + payload = json.loads(path.read_text(encoding="utf-8")) + if payload.get("artifact") != "HISTORICAL_FEATURE_ORACLE_V1_REQUEST" or payload.get("engine_revision") != ENGINE_REVISION: + raise ValueError("unsupported request artifact or engine revision") + if payload.get("input_columns") != list(REQUIRED_COLUMNS) or payload.get("output_dtype") != "float64": + raise ValueError("unsupported input/output semantics") + rows = payload.get("requests") + if not isinstance(rows, list) or len(rows) != 711: + raise ValueError("full historical request must contain exactly 711 features") + known = {int(row[0]) for row in engine.FAST_POOL} + base = {key: payload[key] for key in ("engine_revision", "input_columns", "output_dtype", "window_policy")} + result = [] + for row in rows: + item = {"request_id": str(row["request_id"]), "indicator_id": int(row["indicator_id"]), "period": int(row["period"]), "p1": float(row["p1"])} + if item["indicator_id"] not in known or item["period"] <= 0 or not np.isfinite(item["p1"]): + raise ValueError(f"invalid historical request: {item['request_id']}") + expected = digest_bytes(canonical({**base, **{key: item[key] for key in ("indicator_id", "period", "p1")}})) + if row.get("semantic_fingerprint") != expected: + raise ValueError(f"semantic fingerprint mismatch: {item['request_id']}") + result.append(item) + if len({row["request_id"] for row in result}) != len(result): + raise ValueError("request IDs must be unique") + return result + + +def checkpoint(path: Path, row: dict[str, Any], values: np.ndarray) -> dict[str, object]: + npy = path / f"{row['request_id']}.npy" + meta = path / f"{row['request_id']}.json" + if npy.is_file() and meta.is_file(): + saved = json.loads(meta.read_text(encoding="utf-8")) + loaded = np.load(npy, allow_pickle=False) + if saved["sha256"] == array_digest(loaded) and tuple(saved["shape"]) == loaded.shape: + return saved + temporary = npy.with_suffix(".tmp.npy") + np.save(temporary, values, allow_pickle=False) + os.replace(temporary, npy) + saved = {**row, "path": npy.name, "dtype": values.dtype.str, "shape": list(values.shape), "sha256": array_digest(values)} + atomic_bytes(meta, canonical(saved) + b"\n") + return saved + + +def wrapper_validate(source: Path, engine: Any, arrays: tuple[np.ndarray, ...], combo: list[float]) -> dict[str, object]: + if len(combo) < 15: + raise ValueError("--wrapper-combo requires at least 15 numeric combo values") + wrapper = importlib.import_module("hyperscalper.paper_replay") + close, high, low, volume = arrays + state = wrapper.compute_combo_state(combo, close, high, low, volume) + slots = ("trend", "signal", "trigger", "confirm", "vol") + for slot, offset in zip(slots, range(0, 15, 3), strict=True): + direct = np.asarray(engine.compute(int(combo[offset]), close, high, low, volume, int(combo[offset + 1]), float(combo[offset + 2])), dtype=np.float64) + if slot not in state or not np.array_equal(direct, np.asarray(state[slot], dtype=np.float64), equal_nan=True): + raise RuntimeError(f"paper_replay wrapper mismatch for {slot}") + return {"status": "PASS", "paper_replay_sha256": digest_file(source / "hyperscalper" / "paper_replay.py")} + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--request", type=Path, required=True) + parser.add_argument("--input-csv", type=Path, required=True) + parser.add_argument("--recovered-source", type=Path, required=True) + parser.add_argument("--output-dir", type=Path, required=True) + parser.add_argument("--pilot-count", type=int, default=3) + parser.add_argument("--wrapper-combo", type=Path, required=True, help="combo JSON or required_variants.json; validates paper_replay") + args = parser.parse_args() + if args.pilot_count < 1: + raise ValueError("--pilot-count must be positive") + args.output_dir.mkdir(parents=True, exist_ok=True) + checkpoints = args.output_dir / "checkpoints" + checkpoints.mkdir(exist_ok=True) + event_log = args.output_dir / "events.jsonl" + status = args.output_dir / "final_status.json" + try: + engine = load_engine(args.recovered_source) + arrays = load_csv(args.input_csv) + requests = load_request(args.request, engine) + if json.loads(args.request.read_text(encoding="utf-8")).get("input_csv_sha256") not in (None, digest_file(args.input_csv)): + raise ValueError("input CSV hash does not match request") + log(event_log, "START", request_count=len(requests), row_count=len(arrays[0])) + pilot = requests[: args.pilot_count] + started = time.perf_counter() + for row in pilot: + values = np.asarray(engine.compute(row["indicator_id"], *arrays, row["period"], row["p1"]), dtype=np.float64) + if values.shape != arrays[0].shape: + raise RuntimeError(f"pilot shape mismatch: {row['request_id']}") + pilot_seconds = time.perf_counter() - started + log(event_log, "PILOT_PASS", count=len(pilot), seconds=pilot_seconds, seconds_per_feature=pilot_seconds / len(pilot)) + raw = json.loads(args.wrapper_combo.read_text(encoding="utf-8")) + if isinstance(raw, dict) and "combos" in raw: + raw = raw["combos"][0] + combo = raw.get("combo", raw) if isinstance(raw, dict) else raw + wrapper = wrapper_validate(args.recovered_source, engine, arrays, combo) + log(event_log, "WRAPPER_VALIDATION", **wrapper) + records = [] + for number, row in enumerate(requests, start=1): + values = np.asarray(engine.compute(row["indicator_id"], *arrays, row["period"], row["p1"]), dtype=np.float64) + if values.shape != arrays[0].shape: + raise RuntimeError(f"shape mismatch: {row['request_id']}") + record = checkpoint(checkpoints, row, values) + records.append(record) + log(event_log, "CHECKPOINT", number=number, request_id=row["request_id"], sha256=record["sha256"]) + representative = requests[len(requests) // 2] + first = np.load(checkpoints / f"{representative['request_id']}.npy", allow_pickle=False) + second = np.asarray(engine.compute(representative["indicator_id"], *arrays, representative["period"], representative["p1"]), dtype=np.float64) + if not np.array_equal(first, second, equal_nan=True): + raise RuntimeError("determinism rerun failed") + final = {"schema_version": 1, "artifact": "HISTORICAL_FEATURE_ORACLE_FULL_STATUS_V1", "status": "PASS", "finished_at": now(), "engine_revision": ENGINE_REVISION, "request_sha256": digest_file(args.request), "input_csv_sha256": digest_file(args.input_csv), "engine_sha256": digest_file(args.recovered_source / "hyperscalper" / "fast_engine.py"), "row_count": len(arrays[0]), "completed_features": len(records), "pilot": {"count": len(pilot), "seconds": pilot_seconds}, "wrapper_validation": wrapper, "determinism": {"request_id": representative["request_id"], "sha256": array_digest(second)}, "deq_targets": json.loads(args.request.read_text(encoding="utf-8")).get("deq_targets"), "checkpoints": records} + atomic_bytes(status, canonical(final) + b"\n") + log(event_log, "PASS", completed_features=len(records)) + except Exception as error: + failure = {"schema_version": 1, "artifact": "HISTORICAL_FEATURE_ORACLE_FULL_STATUS_V1", "status": "FAIL", "finished_at": now(), "error": f"{type(error).__name__}: {error}"} + atomic_bytes(status, canonical(failure) + b"\n") + log(event_log, "FAIL", error=failure["error"]) + raise + + +if __name__ == "__main__": + main() diff --git a/run_historical_oracle_overnight.sh b/run_historical_oracle_overnight.sh new file mode 100644 index 0000000..c49ac4e --- /dev/null +++ b/run_historical_oracle_overnight.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +# Copy this file and the two Python scripts to Spark; paths are intentionally explicit. +set -euo pipefail + +: "${RECOVERED_SOURCE:?set to code-5056feb/src}" +: "${INPUT_CSV:?set to canonical OHLCV CSV}" +ROOT=${ROOT:-"$(pwd)"} +: "${WRAPPER_COMBO:=$ROOT/required_variants.json}" +REQUEST=${REQUEST:-"$ROOT/hs22_full_oracle_request.json"} +OUTPUT_DIR=${OUTPUT_DIR:-"$ROOT/hs22_full_oracle_run"} + +request_args=(--usage-summary "$ROOT/historical_feature_usage_v1_summary.json" --engineering-map "$ROOT/engineering_family_map_v1.json" --input-csv "$INPUT_CSV" --output "$REQUEST") +[[ -n "${DEQ_TARGETS:-}" ]] && request_args+=(--deq-targets "$DEQ_TARGETS") +python3 "$ROOT/generate_full_historical_oracle_request.py" "${request_args[@]}" + +run_args=(--request "$REQUEST" --input-csv "$INPUT_CSV" --recovered-source "$RECOVERED_SOURCE" --output-dir "$OUTPUT_DIR" --wrapper-combo "$WRAPPER_COMBO") +python3 "$ROOT/run_historical_oracle_overnight.py" "${run_args[@]}" diff --git a/scripts/analyze_historical_feature_usage_v1.py b/scripts/analyze_historical_feature_usage_v1.py new file mode 100644 index 0000000..dc8657b --- /dev/null +++ b/scripts/analyze_historical_feature_usage_v1.py @@ -0,0 +1,270 @@ +"""Build source-only feature-usage and registry-coverage archaeology artifacts.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +from collections import Counter, defaultdict +from pathlib import Path + +import pyarrow as pa +import pyarrow.parquet as pq + + +ROLES = ("trend", "signal", "trigger", "confirm", "vol") +FRONTIER_TARGETS = (80, 90, 95, 98, 99, 100) + + +def canonical_key(indicator_id: int, period: int, p1: float) -> tuple[int, int, float]: + return indicator_id, period, float(p1) + + +def key_text(key: tuple[int, int, float]) -> str: + return f"{key[0]}:{key[1]}:{key[2]:g}" + + +def digest(path: Path) -> str: + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def frontier(counts: Counter[object]) -> list[dict[str, object]]: + total = sum(counts.values()) + ordered = sorted(counts.items(), key=lambda item: (-item[1], str(item[0]))) + result = [] + cumulative = 0 + cursor = 0 + for target in FRONTIER_TARGETS: + threshold = total * target / 100 + while cursor < len(ordered) and cumulative < threshold: + cumulative += ordered[cursor][1] + cursor += 1 + result.append( + { + "target_percent": target, + "items_required": cursor, + "cumulative_usage": cumulative, + "cumulative_percent": cumulative * 100 / total if total else 0.0, + } + ) + return result + + +def load_catalog(path: Path) -> dict[tuple[int, int, float], str]: + payload = json.loads(path.read_text(encoding="utf-8")) + return { + canonical_key(item["indicator_id"], item["period"], item["p1"]): item["support_state"] + for item in payload["features"] + } + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--lineage", type=Path, required=True) + parser.add_argument("--cohort-manifest", type=Path, required=True) + parser.add_argument("--feature-catalog", type=Path, required=True) + parser.add_argument("--output-dir", type=Path, required=True) + args = parser.parse_args() + + output_dir = args.output_dir + output_dir.mkdir(parents=True, exist_ok=True) + catalog = load_catalog(args.feature_catalog) + cohort = json.loads(args.cohort_manifest.read_text(encoding="utf-8")) + cohort_members = cohort["members"] + + cohort_by_family: dict[str, list[dict[str, object]]] = defaultdict(list) + cohort_by_strategy_id: dict[int, str] = {} + for member in cohort_members: + combo = member["combo"] + triples = tuple( + canonical_key(int(combo[index]), int(combo[index + 1]), float(combo[index + 2])) + for index in range(0, 15, 3) + ) + family = json.dumps(triples, separators=(",", ":")) + cohort_by_family[family].append(member) + cohort_by_strategy_id[int(member["source_strategy_id"])] = family + + id_counts: Counter[int] = Counter() + primitive_counts: Counter[tuple[int, int, float]] = Counter() + role_counts: Counter[str] = Counter() + role_triple_counts: Counter[tuple[str, int, int, float]] = Counter() + family_counts: Counter[str] = Counter() + primitive_roles: dict[tuple[int, int, float], Counter[str]] = defaultdict(Counter) + found_cohort_strategy_ids: set[int] = set() + + source = pq.ParquetFile(args.lineage) + rows = 0 + for batch in source.iter_batches(columns=["strategy_id", "combo_json"], batch_size=65_536): + for record in batch.to_pylist(): + combo = json.loads(record["combo_json"]) + if len(combo) < 15: + raise ValueError(f"strategy {record['strategy_id']} has an incomplete primitive combo") + triples = tuple( + canonical_key(int(combo[index]), int(combo[index + 1]), float(combo[index + 2])) + for index in range(0, 15, 3) + ) + family = json.dumps(triples, separators=(",", ":")) + strategy_id = int(record["strategy_id"]) + expected_family = cohort_by_strategy_id.get(strategy_id) + if expected_family is not None: + if family != expected_family: + raise ValueError(f"cohort strategy {strategy_id} does not match its manifest combo") + found_cohort_strategy_ids.add(strategy_id) + family_counts[family] += 1 + rows += 1 + for role, primitive in zip(ROLES, triples, strict=True): + indicator_id, period, p1 = primitive + id_counts[indicator_id] += 1 + primitive_counts[primitive] += 1 + role_counts[role] += 1 + role_triple_counts[(role, indicator_id, period, p1)] += 1 + primitive_roles[primitive][role] += 1 + + if rows != source.metadata.num_rows: + raise ValueError("Parquet batch iteration did not cover every lineage row") + if found_cohort_strategy_ids != set(cohort_by_strategy_id): + raise ValueError("not every cohort source_strategy_id is present in the lineage") + + cohort_family_counts = {family: len(members) for family, members in cohort_by_family.items()} + cohort_primitive_counts: Counter[tuple[int, int, float]] = Counter() + cohort_role_triple_counts: Counter[tuple[str, int, int, float]] = Counter() + for family, members in cohort_by_family.items(): + triples = json.loads(family) + for _member in members: + for role, raw in zip(ROLES, triples, strict=True): + primitive = canonical_key(*raw) + cohort_primitive_counts[primitive] += 1 + cohort_role_triple_counts[(role, *primitive)] += 1 + + usage_rows: list[dict[str, object]] = [] + for indicator_id, count in id_counts.items(): + usage_rows.append({"entity_type": "indicator_id", "indicator_id": indicator_id, "usage_count": count}) + for role, count in role_counts.items(): + usage_rows.append({"entity_type": "role", "role": role, "usage_count": count}) + for primitive, count in primitive_counts.items(): + usage_rows.append( + { + "entity_type": "primitive", + "primitive": key_text(primitive), + "indicator_id": primitive[0], + "period": primitive[1], + "p1": primitive[2], + "usage_count": count, + "cohort_usage_count": cohort_primitive_counts[primitive], + "classification": catalog.get(primitive, "unregistered"), + } + ) + for (role, indicator_id, period, p1), count in role_triple_counts.items(): + primitive = canonical_key(indicator_id, period, p1) + usage_rows.append( + { + "entity_type": "role_triple", + "role": role, + "primitive": key_text(primitive), + "indicator_id": indicator_id, + "period": period, + "p1": p1, + "usage_count": count, + "cohort_usage_count": cohort_role_triple_counts[(role, indicator_id, period, p1)], + "classification": catalog.get(primitive, "unregistered"), + } + ) + for family, count in family_counts.items(): + members = cohort_by_family.get(family, []) + usage_rows.append( + { + "entity_type": "base_family", + "base_family_signature": family, + "usage_count": count, + "cohort_usage_count": len(members), + "cohort_base_families": ",".join(str(member["base_family"]) for member in members) or None, + } + ) + + usage_path = output_dir / "historical_feature_usage_v1.parquet" + pq.write_table(pa.Table.from_pylist(usage_rows), usage_path, compression="zstd") + + primitive_registry = [] + for primitive, count in sorted(primitive_counts.items(), key=lambda item: (-item[1], item[0])): + classification = catalog.get(primitive, "unregistered") + primitive_registry.append( + { + "primitive": key_text(primitive), + "indicator_id": primitive[0], + "period": primitive[1], + "p1": primitive[2], + "usage_count": count, + "usage_percent": count * 100 / (rows * len(ROLES)), + "roles": dict(sorted(primitive_roles[primitive].items())), + "cohort_usage_count": cohort_primitive_counts[primitive], + "classification": classification, + "currently_validated": classification == "validated", + } + ) + registry_payload = { + "schema_version": 1, + "artifact": "HISTORICAL_PRIMITIVE_REGISTRY_COVERAGE_V1", + "lineage_rows": rows, + "primitive_slots": rows * len(ROLES), + "observed_primitives": len(primitive_counts), + "currently_validated_formula_variants": sum( + classification == "validated" for classification in catalog.values() + ), + "observed_currently_validated_primitives": sum( + item["currently_validated"] for item in primitive_registry + ), + "weighted_primitive_frontier": frontier(primitive_counts), + "primitives": primitive_registry, + } + registry_path = output_dir / "historical_primitive_registry_coverage_v1.json" + registry_path.write_text(json.dumps(registry_payload, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + summary = { + "schema_version": 1, + "artifact": "HISTORICAL_FEATURE_USAGE_SUMMARY_V1", + "source": { + "lineage": str(args.lineage), + "lineage_sha256": digest(args.lineage), + "lineage_rows": rows, + "cohort_manifest": str(args.cohort_manifest), + "cohort_manifest_sha256": digest(args.cohort_manifest), + }, + "counts": { + "unique_strategy_ids": rows, + "primitive_slots": rows * len(ROLES), + "indicator_ids": len(id_counts), + "exact_role_triples": len(role_triple_counts), + "role_independent_primitives": len(primitive_counts), + "roles": len(role_counts), + "base_families": len(family_counts), + "cohort_members": len(cohort_members), + "cohort_source_strategy_ids_found": len(found_cohort_strategy_ids), + "cohort_base_families_found": sum(family in family_counts for family in cohort_by_family), + "cohort_role_triples": len(cohort_role_triple_counts), + "cohort_primitives": len(cohort_primitive_counts), + "currently_validated_formula_variants": sum( + classification == "validated" for classification in catalog.values() + ), + "observed_currently_validated_primitives": sum( + catalog.get(primitive) == "validated" for primitive in primitive_counts + ), + }, + "role_usage": dict(sorted(role_counts.items())), + "weighted_cumulative_frontiers": { + "role_triples": frontier(role_triple_counts), + "primitives": frontier(primitive_counts), + }, + "artifacts": { + "usage_parquet": str(usage_path), + "primitive_registry_coverage": str(registry_path), + }, + } + summary_path = output_dir / "historical_feature_usage_v1_summary.json" + summary_path.write_text(json.dumps(summary, indent=2, sort_keys=True) + "\n", encoding="utf-8") + summary["artifacts"]["usage_parquet_sha256"] = digest(usage_path) + summary["artifacts"]["primitive_registry_coverage_sha256"] = digest(registry_path) + summary_path.write_text(json.dumps(summary, indent=2, sort_keys=True) + "\n", encoding="utf-8") + + +if __name__ == "__main__": + main() diff --git a/scripts/generate_coverage_frontier_v1.py b/scripts/generate_coverage_frontier_v1.py new file mode 100644 index 0000000..1c8278e --- /dev/null +++ b/scripts/generate_coverage_frontier_v1.py @@ -0,0 +1,282 @@ +"""Build metadata-only historical coverage and 95% implementation artifacts. + +This consumes usage aggregates, registry metadata, and the feature catalog. It +never imports, evaluates, or ports indicator formulas. +""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import math +from collections import Counter +from pathlib import Path + +DENOMINATOR = 3_514_830 +TARGETS = (80, 90, 95, 98, 99, 100) +STATE_TO_CLASSIFICATION = { + "validated": "native", + "source_implemented_unvalidated": "missing", + "alias_refused": "unsafe", + "unregistered": "ambiguous", +} +CLASSIFICATIONS = ("native", "missing", "unsafe", "ambiguous") + + +def canonical_json(payload: object) -> bytes: + return json.dumps(payload, sort_keys=True, separators=(",", ":"), allow_nan=False).encode( + "ascii" + ) + + +def sha256(path: Path) -> str: + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def frontier(rows: list[dict[str, object]]) -> list[dict[str, object]]: + cumulative = 0 + cursor = 0 + output = [] + for target in TARGETS: + threshold = math.ceil(DENOMINATOR * target / 100) + while cursor < len(rows) and cumulative < threshold: + cumulative += int(rows[cursor]["usage_slots"]) + cursor += 1 + output.append( + { + "target_percent": target, + "minimum_slots": threshold, + "canonical_items_required": cursor, + "cumulative_slots": cumulative, + "cumulative_percent": cumulative * 100 / DENOMINATOR, + } + ) + return output + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--usage-dir", type=Path, required=True) + parser.add_argument("--feature-catalog", type=Path, required=True) + parser.add_argument("--registry", type=Path, required=True) + parser.add_argument("--output-dir", type=Path, required=True) + args = parser.parse_args() + + usage_dir = args.usage_dir + summary_path = usage_dir / "historical_feature_usage_v1_summary.json" + primitive_path = usage_dir / "historical_primitive_registry_coverage_v1.json" + parquet_path = usage_dir / "historical_feature_usage_v1.parquet" + summary = json.loads(summary_path.read_text(encoding="utf-8")) + primitive_coverage = json.loads(primitive_path.read_text(encoding="utf-8")) + catalog = json.loads(args.feature_catalog.read_text(encoding="utf-8")) + registry = json.loads(args.registry.read_text(encoding="utf-8")) + + if summary["counts"]["primitive_slots"] != DENOMINATOR: + raise ValueError("Historical usage denominator does not equal 3,514,830 slots.") + if primitive_coverage["primitive_slots"] != DENOMINATOR: + raise ValueError("Primitive coverage denominator does not equal 3,514,830 slots.") + + catalog_by_key = { + (item["indicator_id"], item["period"], float(item["p1"])): item + for item in catalog["features"] + } + definitions = {item["indicator_id"]: item for item in registry["definitions"]} + # The registry coverage artifact retains each primitive's per-role slot + # counts, so no formula runtime or Parquet reader is required here. + role_triples = [ + { + "role": role, + "primitive": item["primitive"], + "usage_count": count, + } + for item in primitive_coverage["primitives"] + for role, count in item["roles"].items() + ] + triples_by_primitive: dict[str, list[dict[str, object]]] = {} + for row in role_triples: + triples_by_primitive.setdefault(str(row["primitive"]), []).append(row) + + primitives: list[dict[str, object]] = [] + for source in primitive_coverage["primitives"]: + key = source["indicator_id"], source["period"], float(source["p1"]) + catalog_item = catalog_by_key.get(key) + support_state = catalog_item["support_state"] if catalog_item else "unregistered" + classification = STATE_TO_CLASSIFICATION.get(support_state, "ambiguous") + definition = definitions.get(source["indicator_id"]) + triples = sorted( + triples_by_primitive.get(source["primitive"], []), key=lambda item: item["role"] + ) + primitives.append( + { + "primitive": source["primitive"], + "indicator_id": source["indicator_id"], + "period": source["period"], + "p1": source["p1"], + "usage_slots": source["usage_count"], + "usage_percent": source["usage_count"] * 100 / DENOMINATOR, + "roles": source["roles"], + "role_triples": [ + {"role": item["role"], "usage_slots": item["usage_count"]} for item in triples + ], + "role_triple_count": len(triples), + "duplicate_role_assignments": max(0, len(triples) - 1), + "cohort_usage_count": source["cohort_usage_count"], + "support_state": support_state, + "coverage_classification": classification, + "causal_classification": ( + catalog_item["causal_classification"] if catalog_item else "not_executable" + ), + "indicator_name": definition["name"] if definition else "UNKNOWN", + "registry_status": definition["status"] if definition else "unregistered", + "alias_of": definition["alias_of"] if definition else None, + } + ) + primitives.sort(key=lambda item: (-int(item["usage_slots"]), str(item["primitive"]))) + primitive_frontier = frontier(primitives) + + role_triple_rows = [ + { + "role_triple": f"{row['role']}:{row['primitive']}", + "usage_slots": row["usage_count"], + } + for row in role_triples + ] + role_triple_rows.sort(key=lambda item: (-int(item["usage_slots"]), str(item["role_triple"]))) + role_triple_frontier = frontier(role_triple_rows) + + class_counts = Counter({classification: 0 for classification in CLASSIFICATIONS}) + class_counts.update(item["coverage_classification"] for item in primitives) + class_slots = Counter({classification: 0 for classification in CLASSIFICATIONS}) + for item in primitives: + class_slots[str(item["coverage_classification"])] += int(item["usage_slots"]) + aliases = [item for item in primitives if item["registry_status"] == "alias"] + registry_aliases = [ + { + "indicator_id": item["indicator_id"], + "indicator_name": item["name"], + "alias_of": item["alias_of"], + "behavior": item["behavior"], + "observed_primitives": sum( + primitive["indicator_id"] == item["indicator_id"] for primitive in primitives + ), + } + for item in registry["definitions"] + if item["status"] == "alias" + ] + duplicate_primitives = [ + item for item in primitives if int(item["duplicate_role_assignments"]) > 0 + ] + frontier_80_count = next( + item["canonical_items_required"] + for item in primitive_frontier + if item["target_percent"] == 80 + ) + frontier_95_count = next( + item["canonical_items_required"] + for item in primitive_frontier + if item["target_percent"] == 95 + ) + selected = primitives[:frontier_95_count] + selected_slots = sum(int(item["usage_slots"]) for item in selected) + plan = [] + for index, item in enumerate(selected, start=1): + if item["coverage_classification"] == "native": + continue + item = dict(item) + item["weighted_rank"] = index + item["priority"] = "P0" if index <= frontier_80_count else "P1" + item["action"] = { + "missing": "implement_and_validate", + "unsafe": "retain_refusal_and_recover_alias_semantics", + "ambiguous": "recover_metadata_before_implementation", + }[str(item["coverage_classification"])] + plan.append(item) + + source = { + "historical_usage_summary": {"path": str(summary_path), "sha256": sha256(summary_path)}, + "primitive_registry_coverage": { + "path": str(primitive_path), + "sha256": sha256(primitive_path), + }, + "usage_parquet": {"path": str(parquet_path), "sha256": sha256(parquet_path)}, + "feature_catalog": { + "path": str(args.feature_catalog), + "sha256": sha256(args.feature_catalog), + }, + "historical_registry": {"path": str(args.registry), "sha256": sha256(args.registry)}, + } + coverage = { + "schema_version": 1, + "artifact": "COVERAGE_FRONTIER_V1", + "method": ( + "historical usage aggregation plus registry and feature-catalog metadata; " + "no formula evaluation, database access, or DEQ" + ), + "denominator": { + "primitive_slots": DENOMINATOR, + "lineage_rows": 702_966, + "slots_per_row": 5, + }, + "source_artifacts": source, + "counts": { + "canonical_primitives": len(primitives), + "role_triples": len(role_triples), + "native_formula_variants": 80, + "classifications": dict(sorted(class_counts.items())), + "classification_slots": dict(sorted(class_slots.items())), + "aliases_observed": len(aliases), + "registry_aliases": len(registry_aliases), + "cross_role_duplicate_primitives": len(duplicate_primitives), + }, + "frontiers": { + "canonical_primitives": primitive_frontier, + "role_triples": role_triple_frontier, + }, + "canonical_primitives": primitives, + "aliases": aliases, + "registry_alias_metadata": registry_aliases, + "duplicate_primitives": duplicate_primitives, + } + implementation = { + "schema_version": 1, + "artifact": "FEATURE_95PCT_IMPLEMENTATION_PLAN_V1", + "method": coverage["method"], + "denominator": coverage["denominator"], + "source_artifacts": source, + "target": { + "coverage_percent": 95, + "minimum_slots": math.ceil(DENOMINATOR * 0.95), + "selected_canonical_primitives": frontier_95_count, + "selected_cumulative_slots": selected_slots, + "selected_cumulative_percent": selected_slots * 100 / DENOMINATOR, + }, + "native_coverage": { + "formula_variants": 80, + "selected_native_primitives": sum( + item["coverage_classification"] == "native" for item in selected + ), + "selected_native_slots": sum( + int(item["usage_slots"]) + for item in selected + if item["coverage_classification"] == "native" + ), + }, + "actual_plan_size": len(plan), + "plan_classifications": { + classification: sum(item["coverage_classification"] == classification for item in plan) + for classification in CLASSIFICATIONS + }, + "plan": plan, + "excluded_after_95_frontier": len(primitives) - frontier_95_count, + } + args.output_dir.mkdir(parents=True, exist_ok=True) + coverage_path = args.output_dir / "coverage_frontier_v1.json" + plan_path = args.output_dir / "feature_95pct_implementation_plan_v1.json" + coverage_path.write_bytes(canonical_json(coverage) + b"\n") + implementation["coverage_frontier_sha256"] = sha256(coverage_path) + plan_path.write_bytes(canonical_json(implementation) + b"\n") + + +if __name__ == "__main__": + main() diff --git a/scripts/generate_engineering_family_map_v1.py b/scripts/generate_engineering_family_map_v1.py new file mode 100644 index 0000000..6cd4591 --- /dev/null +++ b/scripts/generate_engineering_family_map_v1.py @@ -0,0 +1,330 @@ +"""Generate metadata-only engineering maps for the observed historical frontier. + +The historical dispatcher is parsed as source text. No formula module is +imported, evaluated, copied, or otherwise ported by this generator. +""" + +from __future__ import annotations + +import argparse +import ast +import hashlib +import json +from pathlib import Path + +import pyarrow as pa +import pyarrow.parquet as pq + +FRONTIER_SIZE = 568 +ROLES = ("trend", "signal", "trigger", "confirm", "vol") +FAMILY_PREFIXES = ( + ("ma_", "moving_average"), + ("osc_", "oscillator"), + ("vol_", "volatility"), + ("regime_", "regime"), + ("micro_", "microstructure"), + ("mom_", "momentum"), + ("trend_", "trend_structure"), + ("norm_", "normalization"), + ("cross_", "cross_indicator"), + ("time_", "time_session"), + ("pivot_", "reference_level"), + ("prev_", "reference_level"), + ("rolling_", "reference_level"), + ("linreg_channel_", "reference_level"), + ("quantile_", "reference_level"), + ("donch_", "band_channel"), + ("kelt_", "band_channel"), + ("bb_", "band_channel"), + ("ichimoku_", "band_channel"), + ("supertrend", "band_channel"), + ("psar", "band_channel"), + ("adx", "trend_structure"), + ("aroon_", "trend_structure"), + ("linreg_", "trend_structure"), + ("entropy_", "regime"), +) + + +def digest(path: Path) -> str: + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def canonical_json(payload: object) -> bytes: + return json.dumps(payload, sort_keys=True, separators=(",", ":"), allow_nan=False).encode( + "ascii" + ) + + +def function_calls(node: ast.AST, functions: set[str]) -> list[str]: + return [ + child.func.id + for child in ast.walk(node) + if ( + isinstance(child, ast.Call) + and isinstance(child.func, ast.Name) + and child.func.id in functions + ) + ] + + +def source_map(path: Path) -> dict[int, dict[str, object]]: + tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path)) + functions = {node.name: node for node in tree.body if isinstance(node, ast.FunctionDef)} + dispatcher = functions.get("compute_indicator") + if dispatcher is None: + raise ValueError("historical source has no compute_indicator dispatcher") + mapping: dict[int, dict[str, object]] = {} + for node in ast.walk(dispatcher): + if not isinstance(node, ast.Compare) or len(node.ops) != 1: + continue + if not ( + isinstance(node.left, ast.Name) + and node.left.id == "ind_id" + and isinstance(node.ops[0], ast.Eq) + and len(node.comparators) == 1 + and isinstance(node.comparators[0], ast.Constant) + and isinstance(node.comparators[0].value, int) + ): + continue + parent = next( + ( + candidate + for candidate in ast.walk(dispatcher) + if isinstance(candidate, ast.If) and candidate.test is node + ), + None, + ) + if parent is None: + continue + returned = next((item.value for item in parent.body if isinstance(item, ast.Return)), None) + if returned is None: + continue + calls = function_calls(returned, set(functions)) + primary = calls[0] if calls else None + if primary is None: + continue + signature = functions[primary].args + inputs = [ + argument.arg + for argument in signature.args + if argument.arg in {"close", "high", "low", "volume"} + ] + dependencies = sorted(set(function_calls(functions[primary], set(functions))) - {primary}) + mapping[node.comparators[0].value] = { + "function": primary, + "source_expression": ast.unparse(returned), + "required_inputs": inputs, + "helper_dependencies": dependencies, + } + return mapping + + +def family(function: str) -> str: + for prefix, value in FAMILY_PREFIXES: + if function.startswith(prefix): + return value + return "specialized" + + +def counts(rows: list[dict[str, object]]) -> dict[str, int]: + return { + "primitives": len(rows), + "indicator_ids": len({int(row["indicator_id"]) for row in rows}), + "functions": len({str(row["source_function"]) for row in rows}), + "families": len({str(row["engineering_family"]) for row in rows}), + "parameter_expansions": len(rows) - len({int(row["indicator_id"]) for row in rows}), + "role_duplicates": sum(int(row["role_triple_count"]) - 1 for row in rows), + "native_reuse_primitives": sum( + row["implementation_path"] == "native_reuse" for row in rows + ), + "native_reuse_functions": len( + { + str(row["source_function"]) + for row in rows + if row["implementation_path"] == "native_reuse" + } + ), + "new_algorithm_primitives": sum( + row["implementation_path"] == "new_algorithm" for row in rows + ), + "new_algorithm_functions": len( + { + str(row["source_function"]) + for row in rows + if row["implementation_path"] == "new_algorithm" + } + ), + "alias_refused_primitives": sum( + row["implementation_path"] == "alias_refused" for row in rows + ), + } + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--coverage", type=Path, required=True) + parser.add_argument("--registry", type=Path, required=True) + parser.add_argument("--historical-source", type=Path, required=True) + parser.add_argument("--output-dir", type=Path, required=True) + args = parser.parse_args() + + coverage = json.loads(args.coverage.read_text(encoding="utf-8")) + registry = json.loads(args.registry.read_text(encoding="utf-8")) + source = source_map(args.historical_source) + definitions = {item["indicator_id"]: item for item in registry["definitions"]} + rows: list[dict[str, object]] = [] + for rank, primitive in enumerate(coverage["canonical_primitives"], start=1): + indicator_id = int(primitive["indicator_id"]) + source_item = source.get(indicator_id) + if source_item is None: + raise ValueError( + f"observed indicator {indicator_id} is absent from the historical dispatcher" + ) + definition = definitions[indicator_id] + source_function = str(source_item["function"]) + rows.append( + { + "weighted_rank": rank, + "frontier": "95" if rank <= FRONTIER_SIZE else "95_to_100", + **primitive, + "registry_id": indicator_id, + "registry_name": definition["name"], + "registry_alias_of": definition["alias_of"], + "registry_behavior": definition["behavior"], + "source_function": source_function, + "source_expression": source_item["source_expression"], + "engineering_family": family(source_function), + "parameter_aliases": {"period": "period", "p1": "p1"}, + "required_inputs": source_item["required_inputs"], + "helper_dependencies": source_item["helper_dependencies"], + "implementation_path": ( + "alias_refused" if definition["status"] == "alias" else "unclassified" + ), + } + ) + if len(rows) != 711 or len(rows[:FRONTIER_SIZE]) != FRONTIER_SIZE: + raise ValueError("expected exactly 711 observed primitives and a 568-item 95% frontier") + native_functions = { + str(row["source_function"]) for row in rows if row["coverage_classification"] == "native" + } + for row in rows: + if row["implementation_path"] == "alias_refused": + continue + row["implementation_path"] = ( + "native_reuse" if row["source_function"] in native_functions else "new_algorithm" + ) + + selected, delta = rows[:FRONTIER_SIZE], rows[FRONTIER_SIZE:] + total_slots = sum(int(row["usage_slots"]) for row in rows) + selected_slots = sum(int(row["usage_slots"]) for row in selected) + leverage = { + "slots_per_new_algorithm_function": ( + selected_slots / counts(selected)["new_algorithm_functions"] + ), + "primitives_per_new_algorithm_function": ( + counts(selected)["new_algorithm_primitives"] + / counts(selected)["new_algorithm_functions"] + ), + "parameter_expansions_per_function": ( + counts(selected)["parameter_expansions"] / counts(selected)["functions"] + ), + "role_assignments_per_primitive": ( + sum(int(row["role_triple_count"]) for row in selected) / len(selected) + ), + } + family_rows = [] + for name in sorted({str(row["engineering_family"]) for row in rows}): + items = [row for row in rows if row["engineering_family"] == name] + family_rows.append( + { + "engineering_family": name, + "counts": counts(items), + "usage_slots": sum(int(row["usage_slots"]) for row in items), + } + ) + source_artifacts = { + "coverage": {"path": str(args.coverage), "sha256": digest(args.coverage)}, + "registry": {"path": str(args.registry), "sha256": digest(args.registry)}, + "historical_source": { + "path": str(args.historical_source), + "sha256": digest(args.historical_source), + }, + } + family_payload = { + "schema_version": 1, + "artifact": "ENGINEERING_FAMILY_MAP_V1", + "method": ( + "static local archaeology only; historical dispatcher AST and registry metadata; " + "no formula import, evaluation, or port" + ), + "source_artifacts": source_artifacts, + "counts": counts(rows), + "families": family_rows, + "primitives": rows, + } + frontier_payload = { + "schema_version": 1, + "artifact": "IMPLEMENTATION_FRONTIER_V1", + "method": family_payload["method"], + "source_artifacts": source_artifacts, + "frontier_95": { + "primitive_count": len(selected), + "usage_slots": selected_slots, + "coverage_percent": selected_slots * 100 / total_slots, + "counts": counts(selected), + "leverage": leverage, + }, + "full_100": { + "primitive_count": len(rows), + "usage_slots": total_slots, + "coverage_percent": 100.0, + "counts": counts(rows), + }, + "delta_95_to_100": { + "primitive_count": len(delta), + "usage_slots": sum(int(row["usage_slots"]) for row in delta), + "coverage_percent": (total_slots - selected_slots) * 100 / total_slots, + "incremental_counts": counts(delta), + }, + "frontier_primitives": selected, + "delta_primitives": delta, + } + args.output_dir.mkdir(parents=True, exist_ok=True) + (args.output_dir / "engineering_family_map_v1.json").write_bytes( + canonical_json(family_payload) + b"\n" + ) + (args.output_dir / "implementation_frontier_v1.json").write_bytes( + canonical_json(frontier_payload) + b"\n" + ) + parquet_rows = [ + { + **{ + key: value + for key, value in row.items() + if key + not in { + "roles", + "role_triples", + "parameter_aliases", + "required_inputs", + "helper_dependencies", + } + }, + "roles_json": json.dumps(row["roles"], sort_keys=True), + "role_triples_json": json.dumps(row["role_triples"], sort_keys=True), + "parameter_aliases_json": json.dumps(row["parameter_aliases"], sort_keys=True), + "required_inputs_json": json.dumps(row["required_inputs"]), + "helper_dependencies_json": json.dumps(row["helper_dependencies"]), + } + for row in rows + ] + table = pa.Table.from_pylist(parquet_rows) + pq.write_table(table, args.output_dir / "engineering_family_map_v1.parquet", compression="zstd") + pq.write_table( + table, args.output_dir / "implementation_frontier_v1.parquet", compression="zstd" + ) + + +if __name__ == "__main__": + main() diff --git a/tests/test_batch01_native_parity.py b/tests/test_batch01_native_parity.py new file mode 100644 index 0000000..959c8eb --- /dev/null +++ b/tests/test_batch01_native_parity.py @@ -0,0 +1,62 @@ +from __future__ import annotations + +import json + +from control_plane.trading_studio.indicators.batch01_native_parity import ( + batch01_native_parity_manifest, + batch01_native_parity_manifest_bytes, + evaluate_batch01_native_parity, +) + + +def test_batch01_native_parity_manifest_pins_local_oracle_inputs(): + manifest = batch01_native_parity_manifest() + assert manifest["variant_count"] == 97 + assert manifest["comparison"] == { + "dtype": "exact", "shape": "exact", "nan_mask": "exact", "values": "exact" + } + assert manifest["derived_state_transitions"]["indicator_ids"] == [19, 28] + assert manifest["documented_exception"]["global_tolerance"] == "forbidden" + assert json.loads(batch01_native_parity_manifest_bytes()) == manifest + + +def test_all_97_batch01_native_outputs_match_with_only_documented_bollinger_ulp_cases(): + report = evaluate_batch01_native_parity() + state_records = [ + item + for item in report["records"] + if item["name"].endswith((":state", ":transitions")) + ] + assert len(state_records) == 30 + assert all(item["status"] == "pass" for item in state_records) + accepted = [ + item + for item in report["records"] + if item["reason"] == "accepted_documented_float64_ulp_drift" + ] + assert {item["name"] for item in accepted} == { + "batch01_17_14_2", + "batch01_17_18_2", + "batch01_17_20_1.5", + "batch01_18_14_2", + "batch01_18_18_2", + "batch01_18_20_1.5", + } + assert sum(item["value_mismatches"] for item in accepted) == 8 + assert report["acceptance_manifest"]["status"] == "accepted" + coverage = report["acceptance_manifest"]["coverage"] + assert coverage["submitted_feature_versions"] == 97 + assert coverage["passed_feature_versions"] == 97 + assert coverage["submitted_usage_slots"] == 97 + assert coverage["passed_usage_slots"] == 97 + assert coverage["coverage_percent"] == 100.0 + assert len(coverage["feature_versions"]) == 97 + failures = report["failures"] + assert not failures, "\n".join( + f"{item['name']}: {item['reason']} " + f"(dtype {item['expected_dtype']} != {item['actual_dtype']}, " + f"shape {item['expected_shape']} != {item['actual_shape']}, " + f"NaN mismatches={item['nan_mask_mismatches']}, " + f"value mismatches={item['value_mismatches']})" + for item in failures + ) diff --git a/tests/test_batch01_oracle_manifest.py b/tests/test_batch01_oracle_manifest.py new file mode 100644 index 0000000..927e0eb --- /dev/null +++ b/tests/test_batch01_oracle_manifest.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +import hashlib +import json + +from control_plane.trading_studio.indicators.batch01_oracle_manifest import ( + batch01_oracle_request_manifest, + batch01_oracle_request_manifest_bytes, +) +from control_plane.trading_studio.indicators.historical_band_channel import ( + OBSERVED_BAND_CHANNEL_PARAMS, +) + + +def test_batch01_oracle_manifest_has_exact_observed_requests_and_semantic_hashes(): + manifest = batch01_oracle_request_manifest() + requests = manifest["requests"] + assert manifest["artifact"] == "HISTORICAL_FEATURE_ORACLE_V1_REQUEST" + assert manifest["engine_revision"] == "code-5056feb" + assert len(requests) == 97 + assert { + (row["indicator_id"], row["period"], row["p1"]) + for row in requests + } == OBSERVED_BAND_CHANNEL_PARAMS + for row in requests: + semantic = { + "engine_revision": manifest["engine_revision"], + "input_columns": manifest["input_columns"], + "output_dtype": manifest["output_dtype"], + "window_policy": manifest["window_policy"], + "indicator_id": row["indicator_id"], + "period": row["period"], + "p1": row["p1"], + } + assert row["semantic_fingerprint"] == hashlib.sha256( + json.dumps(semantic, sort_keys=True, separators=(",", ":")).encode() + ).hexdigest() + assert json.loads(batch01_oracle_request_manifest_bytes()) == manifest diff --git a/tests/test_cohort_001_specimen.py b/tests/test_cohort_001_specimen.py new file mode 100644 index 0000000..496a04d --- /dev/null +++ b/tests/test_cohort_001_specimen.py @@ -0,0 +1,93 @@ +from inspect import getsource +from types import SimpleNamespace + +from control_plane.trading_studio.management.commands.specimen_hyperscalper_cohort_001 import ( + SCENARIO_NAMES, + Command, +) + + +def _ledger(*, net=8.0): + return { + "gross_pnl": 10.0, + "net_pnl": net, + "entry_commission": 1.0, + "exit_commission": 1.0, + "entry_slippage": 0.25, + "exit_slippage": 0.25, + "funding": 0.0, + "other_cost": 0.0, + "deq": { + "return_1_bars_bps": 5.0, + "return_2_bars_bps": None, + "return_3_bars_bps": None, + "return_5_bars_bps": None, + "return_10_bars_bps": None, + "mfe_bps": 10.0, + "mae_bps": -2.0, + "time_to_positive_bars": 1, + "time_to_25_bps_bars": None, + "time_to_50_bps_bars": None, + "max_adverse_before_positive_bps": -2.0, + "winner_negative_first": True, + "recovery_bars": 1, + }, + } + + +def test_specimen_contract_is_complete_and_limits_execution_to_first_member(): + source = getsource(Command) + + assert len(SCENARIO_NAMES) == 13 + assert "TOTAL_COST_6BP" in SCENARIO_NAMES + assert "STOP_WIDTH_25" in SCENARIO_NAMES + assert "memberships[0]" in source + + +def test_deq_report_aggregates_every_primitive_including_missing_values_and_booleans(): + report = Command._deq_aggregate([_ledger()]) + + assert report["trade_count"] == 1 + assert set(report["fields"]) == set(_ledger()["deq"]) + assert report["fields"]["return_2_bars_bps"] == {"available_count": 0, "mean": None} + assert report["fields"]["winner_negative_first"] == { + "available_count": 1, + "true_count": 1, + "false_count": 0, + } + + +def test_ledger_reconciliation_checks_summary_and_rescue_totals(): + ledger = [_ledger()] + summary = { + "ledger_count": 1, + "gross_pnl": 10.0, + "net_pnl": 8.0, + "rescue": { + "gross_pnl": 10.0, + "net_pnl": 8.0, + "commissions": 2.0, + "slippage": 0.5, + "funding": 0.0, + "other_cost": 0.0, + }, + } + + assert Command._reconcile(summary, ledger)["consistent"] is True + summary["rescue"]["net_pnl"] = 7.0 + assert Command._reconcile(summary, ledger)["consistent"] is False + summary["rescue"]["net_pnl"] = 8.0 + ledger[0]["net_pnl"] = 7.0 + assert Command._reconcile(summary, ledger)["row_pnl_consistent"] is False + + +def test_report_has_machine_and_human_sections_and_refuses_monetization_claim_without_criteria(): + scenario = {"ledger_reconciliation": {"consistent": True}} + cohort = SimpleNamespace(id="cohort", dataset_version_id="dataset", policy_snapshot={}) + membership = SimpleNamespace(ordinal=1, id="member", strategy_version_id="strategy") + + report = Command._report(cohort, membership, [{"fold": "Fold 1", "scenarios": [scenario]}]) + + assert report["machine"]["edge_vs_monetization"]["status"] == "INSUFFICIENT" + assert report["human"]["ledger_reconciled"] is True + assert report["machine"]["member_ordinal"] == 1 diff --git a/tests/test_cohort_qualification_hyperscalper_001.py b/tests/test_cohort_qualification_hyperscalper_001.py new file mode 100644 index 0000000..f2de640 --- /dev/null +++ b/tests/test_cohort_qualification_hyperscalper_001.py @@ -0,0 +1,139 @@ +from inspect import getsource +from types import SimpleNamespace + +import pytest + +from control_plane.trading_studio.management.commands.cohort_qualification_hyperscalper_001 import ( + CONTRACT, + RUNNER_NAME, + Command, +) +from control_plane.trading_studio.management.commands.specimen_hyperscalper_cohort_001 import ( + Command as SpecimenCommand, + SCENARIO_NAMES, +) + + +def _ledger(net_pnl=1.0): + return { + "exit_reason": "TP", + "take_profit_price": 101.0, + "entry_execution_price": 100.0, + "net_pnl": net_pnl, + "deq": { + "return_1_bars_bps": 10.0, + "return_2_bars_bps": None, + "return_3_bars_bps": None, + "return_5_bars_bps": None, + "return_10_bars_bps": None, + "mfe_bps": 12.0, + "mae_bps": -1.0, + "time_to_positive_bars": 1, + "time_to_25_bps_bars": None, + "time_to_50_bps_bars": None, + "max_adverse_before_positive_bps": -1.0, + "winner_negative_first": True, + "recovery_bars": 1, + }, + } + + +def _legacy_specimen(): + scenario = { + "qualification_run_id": "run", + "scenario": "", + "summary": {}, + "ledger": [], + "ledger_reconciliation": {}, + "deq": {}, + "rescue": {}, + } + return { + "machine": { + "contract": "Cohort001-first-member-specimen-v1", + "member_ordinal": 1, + "fold_count": 4, + "scenario_count_per_fold": 13, + "folds": [ + { + "fold": f"Fold {number}", + "scenarios": [{**scenario, "scenario": name} for name in SCENARIO_NAMES], + } + for number in range(1, 5) + ], + } + } + + +def test_cohort_command_contract_limits_new_execution_to_ordinals_two_through_twenty(): + source = getsource(Command) + + assert CONTRACT == "Cohort001-qualification-v1" + assert RUNNER_NAME.endswith(":v1") + assert len(SCENARIO_NAMES) == 13 + assert "memberships[1:]" in source + assert "QualificationReplayRun.objects.filter" in source + assert "mixed runner versions" in source + assert "CanaryCommand._native_state" in source + assert "--specimen-report-sha" in source + assert "externally frozen SHA" in source + assert "require_protocol_identity=True" in source + assert "specimen_configuration_sha256" not in getsource(SpecimenCommand._report) + assert "allow_empty_raw=True" in source + + +def test_legacy_specimen_validation_requires_contract_four_folds_scenarios_and_ledger_fields(): + report = _legacy_specimen() + + Command._validate_specimen(report) + report["machine"]["folds"][0]["scenarios"][0]["ledger"] = [{"net_pnl": 1.0}] + with pytest.raises(ValueError, match="ledger fields"): + Command._validate_specimen(report) + + +def test_zero_trade_fold_reconciles_without_fabricated_ledger_rows(): + summary = { + "ledger_count": 0, + "gross_pnl": 0.0, + "net_pnl": 0.0, + "rescue": { + "gross_pnl": 0.0, + "net_pnl": 0.0, + "commissions": 0.0, + "slippage": 0.0, + "funding": 0.0, + "other_cost": 0.0, + }, + } + + assert SpecimenCommand._reconcile(summary, [])["consistent"] is True + + +def test_indicator_expansion_reports_required_classes_and_missing_data_transparently(): + expansion = Command._indicator_expansion( + [{"ledger": [_ledger(), _ledger(net_pnl=-1.0)]}] + ) + + assert expansion["status"] == "AVAILABLE" + assert expansion["classes"]["exit_reason"] == {"TP": 2} + assert expansion["classes"]["net_pnl"] == {"LOSS": 1, "WIN": 1} + assert expansion["deq_distributions"]["return_2_bars_bps"] == { + "available_count": 0, + "missing_count": 2, + "status": "INSUFFICIENT", + } + assert "Required classes" in Command._indicator_brief(expansion) + + +def test_machine_and_human_report_bind_catalog_and_external_specimen_hashes(): + cohort = SimpleNamespace(id="cohort") + report = Command._report(cohort, [], "manifest", "dataset", "config", "specimen") + + assert report["machine"]["protocol_identity"] == { + "cohort_manifest_sha256": "manifest", + "dataset_sha256": "dataset", + "qualification_scenario_catalog_sha256": "config", + "specimen_report_sha256": "specimen", + "runner_name": RUNNER_NAME, + } + assert report["human"]["indicator_expansion_status"] == "INSUFFICIENT" diff --git a/tests/test_feature_catalog_v1.py b/tests/test_feature_catalog_v1.py new file mode 100644 index 0000000..fb8ac5e --- /dev/null +++ b/tests/test_feature_catalog_v1.py @@ -0,0 +1,59 @@ +from __future__ import annotations + +import json + +import pytest +from django.core.management import call_command + +from control_plane.trading_studio.indicators.definitions import IndicatorVariant, Role +from control_plane.trading_studio.indicators.feature_catalog import ( + FEATURE_CATALOG_V1, + FEATURE_CATALOG_V1_PATH, + FEATURE_SAFETY_AUDIT_V1_PATH, + CausalClassification, + FeatureSupportState, + FeatureUnavailableError, + feature_catalog_artifact_bytes, + feature_definition, + feature_safety_audit_artifact_bytes, + require_validated_features, +) + + +def test_catalog_explicitly_records_validated_coverage_and_source_only_scope(): + assert len(FEATURE_CATALOG_V1) == 1107 + validated = { + item.key + for item in FEATURE_CATALOG_V1 + if item.support_state == FeatureSupportState.VALIDATED + } + assert len(validated) == 80 + artifact = json.loads(feature_catalog_artifact_bytes()) + assert artifact["implementation_coverage"]["coverage"] == "80 of 1107" + assert artifact["evaluation"] == "not evaluated via reference runtime; no strategy search" + + +def test_safety_audit_derives_causal_classification_from_source_semantics(): + trailing = feature_definition(IndicatorVariant(30, 14, 0.0, Role.OSC)) + index_based = feature_definition(IndicatorVariant(117, 1, 0.0, Role.TREND)) + alias = feature_definition(IndicatorVariant(25, 14, 0.0, Role.LEVEL)) + assert trailing.causal_classification == CausalClassification.TRAILING_WINDOW_CAUSAL + assert index_based.causal_classification == CausalClassification.INDEX_POSITION_CAUSAL + assert alias.support_state == FeatureSupportState.ALIAS_REFUSED + policy = json.loads(feature_safety_audit_artifact_bytes())["fail_closed_policy"] + assert policy.startswith("Any requested") + + +def test_non_validated_historical_variants_fail_closed_without_baseline_expansion(): + validated = IndicatorVariant(30, 14, 0.0, Role.OSC) + unvalidated = IndicatorVariant(30, 12, 0.0, Role.OSC) + with pytest.raises(FeatureUnavailableError, match="fails closed"): + require_validated_features([validated, unvalidated]) + + +def test_generator_writes_machine_readable_catalog_and_audit(tmp_path): + call_command("tradingstudio_generate_feature_catalog", "--output-dir", str(tmp_path)) + catalog = tmp_path / FEATURE_CATALOG_V1_PATH.name + audit = tmp_path / FEATURE_SAFETY_AUDIT_V1_PATH.name + assert json.loads(catalog.read_text())["catalog"] == "FEATURE_CATALOG_V1" + assert json.loads(audit.read_text())["audit"] == "FEATURE_SAFETY_AUDIT_V1" diff --git a/tests/test_feature_parity_harness_v1.py b/tests/test_feature_parity_harness_v1.py new file mode 100644 index 0000000..ebb58ff --- /dev/null +++ b/tests/test_feature_parity_harness_v1.py @@ -0,0 +1,47 @@ +from __future__ import annotations + +import numpy as np +import pytest + +from control_plane.trading_studio.indicators.parity_harness_v1 import ( + FeatureVersion, + ParityStatus, + compare_array, + compare_state, + enumerate_native_evaluators, + load_frozen_engineering_map, + parity_manifest, + recompute_coverage, +) + +pytestmark = pytest.mark.django_db + + +def test_manifest_is_pinned_to_the_frozen_engineering_map(): + assert load_frozen_engineering_map()["counts"]["primitives"] == 711 + assert parity_manifest()["comparison"]["tolerance_by_engineering_family"] == {} + + +def test_comparisons_record_exact_dtype_nan_and_state_key_failures(): + record = compare_array( + "feature", np.array([np.nan, 1.0]), np.array([np.nan, 1.0], dtype=np.float32) + ) + assert record.status == ParityStatus.FAIL + assert record.expected_dtype == "float64" + assert record.nan_mask_mismatches == 0 + state = compare_state( + {"trend": np.array([1], dtype=np.int8)}, + {"signal": np.array([1], dtype=np.int8)}, + ) + assert {item.reason for item in state} == {"state_key_mismatch"} + + +def test_native_enumeration_and_coverage_use_only_submitted_versions(): + passed = FeatureVersion("v1", "p1", "trend", 9, lambda _: np.array([1]), ParityStatus.PASS) + failed = FeatureVersion("v2", "p2", "trend", 1, None, ParityStatus.FAIL) + assert enumerate_native_evaluators([passed, failed]) == (passed,) + assert recompute_coverage([passed, failed]) == { + "submitted_feature_versions": 2, "passed_feature_versions": 1, + "submitted_usage_slots": 10, "passed_usage_slots": 9, + "coverage_percent": 90.0, "feature_versions": ["v1"], + } diff --git a/tests/test_historical_band_channel.py b/tests/test_historical_band_channel.py new file mode 100644 index 0000000..24e3f08 --- /dev/null +++ b/tests/test_historical_band_channel.py @@ -0,0 +1,39 @@ +from __future__ import annotations + +import numpy as np +import pytest + +from control_plane.trading_studio.indicators.historical_band_channel import ( + NATIVE_EVALUATORS, + OBSERVED_BAND_CHANNEL_PARAMS, + evaluate_band_channel, +) +from control_plane.trading_studio.indicators.historical_formulae import compute_indicator + + +def _ohlcv() -> tuple[np.ndarray, ...]: + close = np.linspace(100.0, 140.0, 80) + np.sin(np.arange(80) / 3) + high = close + 1.5 + (np.arange(80) % 3) / 10 + low = close - 1.25 - (np.arange(80) % 4) / 10 + volume = np.linspace(1_000.0, 2_000.0, 80) + return close, high, low, volume + + +def test_batch01_registers_only_the_97_observed_band_channel_primitives(): + assert set(NATIVE_EVALUATORS) == {17, 18, 19, 20, 21, 23, 24, 28} + assert len(OBSERVED_BAND_CHANNEL_PARAMS) == 97 + assert (22, 10, 0.0) not in OBSERVED_BAND_CHANNEL_PARAMS + + +@pytest.mark.parametrize("indicator_id,period,p1", sorted(OBSERVED_BAND_CHANNEL_PARAMS)) +def test_batch01_matches_recovered_historical_formulae(indicator_id: int, period: int, p1: float): + close, high, low, volume = _ohlcv() + actual = evaluate_band_channel(indicator_id, close, high, low, volume, period, p1) + expected = compute_indicator(indicator_id, close, high, low, volume, period, p1) + np.testing.assert_array_equal(actual, expected) + + +def test_batch01_refuses_unobserved_parameter_expansion(): + close, high, low, volume = _ohlcv() + with pytest.raises(ValueError, match="unsupported Batch01"): + evaluate_band_channel(20, close, high, low, volume, 12, 0.0) diff --git a/tests/test_hs22_oracle_parity.py b/tests/test_hs22_oracle_parity.py new file mode 100644 index 0000000..35e8da2 --- /dev/null +++ b/tests/test_hs22_oracle_parity.py @@ -0,0 +1,125 @@ +from __future__ import annotations + +import csv +import json +from hashlib import sha256 +from pathlib import Path + +import numpy as np +import pytest + +from control_plane.trading_studio.indicators.definitions import IndicatorVariant, Role +from control_plane.trading_studio.indicators.engine import compute_hs22_state, evaluate_indicator + + +ORACLE = Path(__file__).resolve().parents[1] / "hs22_oracle_v1" +CSV_SHA256 = "7fb56bb05b0edc2348407765cd693efadf334307c25877dfb52acfe4221e5d00" +# Spark emitted the oracle on NumPy 2.4.6/aarch64; this Windows runner uses +# NumPy 2.4.4. The largest observed arithmetic drift is 1.11e-15 (IDs 79/76). +FLOAT_ATOL = 1.2e-15 +SLOT_ROLE = { + "trend": Role.TREND, + "signal": Role.OSC, + "trigger": Role.LEVEL, + "confirm": Role.OSC, + "vol": Role.FILTER, +} + + +@pytest.fixture(scope="session") +def oracle(): + assert sha256((ORACLE / "binance_btcusdt_spot_2m_180d.csv").read_bytes()).hexdigest() == CSV_SHA256 + manifest = json.loads((ORACLE / "required_variants.json").read_text(encoding="utf-8")) + with (ORACLE / "binance_btcusdt_spot_2m_180d.csv").open(newline="", encoding="utf-8") as handle: + rows = list(csv.DictReader(handle)) + assert len(rows) == 129_599 + return manifest, tuple( + np.asarray([float(row[name]) for row in rows], dtype=np.float64) + for name in ("open", "high", "low", "close", "volume") + ) + + +def _assert_exact(actual: np.ndarray, expected: np.ndarray) -> None: + assert actual.dtype == expected.dtype + assert actual.shape == expected.shape + assert np.array_equal(np.isnan(actual), np.isnan(expected)) + if np.issubdtype(actual.dtype, np.integer): + assert np.array_equal(actual, expected) + else: + np.testing.assert_allclose(actual, expected, rtol=0.0, atol=FLOAT_ATOL, equal_nan=True) + + +def _variant(slot: str, item: dict[str, float]) -> IndicatorVariant: + return IndicatorVariant(int(item["indicator_id"]), int(item["period"]), item["p1"], SLOT_ROLE[slot]) + + +@pytest.fixture(scope="session") +def native_variants(oracle): + manifest, (_, high, low, close, volume) = oracle + outputs = {} + with np.load(ORACLE / "required_variant_arrays.npz") as expected: + for combo in manifest["combos"]: + for slot, item in combo["role_triples"].items(): + variant = _variant(slot, item) + key = (variant.indicator_id, variant.period, variant.p1) + actual = evaluate_indicator(variant, close, high, low, volume) + oracle_key = "v_" + combo["role_variant_fingerprints"][slot] + _assert_exact(actual, expected[oracle_key]) + outputs[key] = actual + assert len(outputs) == 80 + return outputs + + +def test_all_80_required_variant_arrays_match_the_frozen_oracle(native_variants): + assert len(native_variants) == 80 + + +def _decisions(state: dict[str, np.ndarray], close: np.ndarray, combo: list[float]) -> np.ndarray: + vol = state["vol"] + valid = vol[~np.isnan(vol)] + threshold = np.sort(valid)[min(int(combo[21] / 100.0 * len(valid)), len(valid) - 1)] + out = np.zeros(len(close), dtype=np.int8) + signal = state["signal_color"] + trend = state["trend_color"] + common = np.isfinite(state["trigger"]) & np.isfinite(state["confirm"]) & np.isfinite(vol) + common &= vol >= threshold + flips = (signal != np.roll(signal, 1)) & (signal != 0) + long = common & flips & (signal == 1) & (trend == 1) & (close > state["trigger"]) + long &= (combo[17] <= state["confirm"]) & (state["confirm"] <= combo[18]) + short = common & flips & (signal == -1) & (trend == -1) & (close < state["trigger"]) + short &= (combo[19] <= state["confirm"]) & (state["confirm"] <= combo[20]) + out[long] = 1 + out[short] = -1 + return out + + +def test_all_20_hs22_states_and_decisions_match_the_frozen_oracle(oracle): + manifest, (_, high, low, close, volume) = oracle + names = ("trend", "signal", "trigger", "confirm", "vol", "trend_color", "signal_color") + for combo in manifest["combos"]: + actual = compute_hs22_state(combo["combo"], close, high, low, volume) + with np.load(ORACLE / combo["state_file"]) as expected: + for name in names: + _assert_exact(actual[name], expected[name]) + expected_state = {name: expected[name] for name in names} + assert np.count_nonzero(_decisions(actual, close, combo["combo"]) != _decisions(expected_state, close, combo["combo"])) == 0 + + +def test_fold1_context_prefix_matches_continuous_history(native_variants, oracle): + _, (_, high, low, close, volume) = oracle + fold1_test_stop = 14_400 + 35 + 7_200 + fold1_test = slice(14_400 + 35, fold1_test_stop) + for (indicator_id, period, p1), full in native_variants.items(): + # Formula output is role-independent; choose the first registered role for this triple. + for candidate in SLOT_ROLE.values(): + try: + context = evaluate_indicator( + IndicatorVariant(indicator_id, period, p1, candidate), + close[:fold1_test_stop], high[:fold1_test_stop], low[:fold1_test_stop], volume[:fold1_test_stop], + ) + break + except ValueError: + continue + else: + raise AssertionError("required variant lost its strict role registration") + _assert_exact(context[fold1_test], full[fold1_test]) diff --git a/tests/test_hyperscalper_cohort_materialization.py b/tests/test_hyperscalper_cohort_materialization.py new file mode 100644 index 0000000..0abb6c4 --- /dev/null +++ b/tests/test_hyperscalper_cohort_materialization.py @@ -0,0 +1,260 @@ +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) diff --git a/tests/test_indicator_registry.py b/tests/test_indicator_registry.py new file mode 100644 index 0000000..9310319 --- /dev/null +++ b/tests/test_indicator_registry.py @@ -0,0 +1,100 @@ +from __future__ import annotations + +import hashlib +import json + +import pytest + +from control_plane.trading_studio.indicators.definitions import IndicatorVariant, Role +from control_plane.trading_studio.indicators.engine import IndicatorEngine, RefusalCode +from control_plane.trading_studio.indicators.registry import ( + EXPERIMENTAL_UNIVERSE, + HISTORICAL_ARTIFACT_PATH, + HISTORICAL_REGISTRY, + HS22_COHORT001_V1, + HS22_HISTORICAL_COMPLETE_V1, + UNREGISTERED_INDICATORS, + historical_artifact_bytes, + historical_artifact_digest, +) +from control_plane.trading_studio.indicators.schema import HS22SchemaError, parse_hs22 + + +def test_historical_inventory_counts_role_pools_and_digest_are_stable(): + assert len(HISTORICAL_REGISTRY.definitions) == 145 + assert len(HISTORICAL_REGISTRY.variants) == 1107 + assert {role.value: len(HS22_HISTORICAL_COMPLETE_V1.by_role(role)) for role in Role} == { + "level": 493, + "osc": 372, + "trend": 103, + "filter": 139, + } + assert historical_artifact_digest() == ( + "9be2aa3c56c90d2ffc73b64e857092c320fd57b6bbb77a358611a267b52c5ab2" + ) + assert ( + hashlib.sha256(HISTORICAL_ARTIFACT_PATH.read_bytes().rstrip()).hexdigest() + == historical_artifact_digest() + ) + + +def test_artifact_is_machine_readable_and_matches_registry(): + artifact = json.loads(HISTORICAL_ARTIFACT_PATH.read_text()) + assert artifact["definition_count"] == 145 + assert artifact["variant_count"] == 1107 + assert historical_artifact_bytes() == HISTORICAL_ARTIFACT_PATH.read_bytes().rstrip() + + +def test_recovered_boundary_grids_are_not_truncated_or_reclassified(): + assert len([v for v in HISTORICAL_REGISTRY.variants if v.indicator_id == 14]) == 8 + assert len([v for v in HISTORICAL_REGISTRY.variants if v.indicator_id == 28]) == 3 + assert len([v for v in HISTORICAL_REGISTRY.variants if v.indicator_id == 41]) == 8 + clustering = [v for v in HISTORICAL_REGISTRY.variants if v.indicator_id == 62] + assert [v.period for v in clustering] == [10, 15, 20, 25, 30] + assert {v.role for v in clustering} == {Role.TREND} + + +def test_aliases_and_unregistered_metadata_are_explicit(): + assert HISTORICAL_REGISTRY.definition(25).alias_of == 1 + assert HISTORICAL_REGISTRY.definition(26).status.value == "alias" + assert HISTORICAL_REGISTRY.definition(27).status.value == "alias" + assert "MOM_JERK" in UNREGISTERED_INDICATORS + + +def test_unknown_and_unsupported_variants_never_fall_back(): + engine = IndicatorEngine() + unknown = engine.resolve(IndicatorVariant(9999, 14, 0.0, Role.OSC)) + unsupported = engine.resolve(IndicatorVariant(30, 7, 0.0, Role.OSC)) + assert unknown.code == RefusalCode.UNKNOWN_INDICATOR + assert unknown.all_nan_behavior is True + assert unsupported.code == RefusalCode.UNSUPPORTED_VARIANT + + +def test_hs22_parser_requires_registered_role_correct_variants(): + state = parse_hs22( + { + "trend": [70, 10, 0], + "signal": [30, 6, 0], + "trigger": [0, 5, 0], + "confirm": [31, 5, 0], + "volatility": [50, 8, 0], + } + ) + assert state.trend.role == Role.TREND + with pytest.raises(HS22SchemaError, match="no fallback"): + parse_hs22( + { + "trend": [70, 10, 0], + "signal": [30, 7, 0], + "trigger": [0, 5, 0], + "confirm": [31, 5, 0], + "volatility": [50, 8, 0], + } + ) + + +def test_derived_and_experimental_universes_do_not_expand_to_historical_pool(): + assert HS22_COHORT001_V1.namespace == "derived" + assert HS22_COHORT001_V1.variants == () + assert EXPERIMENTAL_UNIVERSE.namespace == "experimental" + assert EXPERIMENTAL_UNIVERSE.variants == () diff --git a/tests/test_qualification_replay_v1.py b/tests/test_qualification_replay_v1.py new file mode 100644 index 0000000..a87a2cb --- /dev/null +++ b/tests/test_qualification_replay_v1.py @@ -0,0 +1,380 @@ +from datetime import UTC, datetime, timedelta + +import pytest + +from control_plane.projects.models import Project +from control_plane.trading_studio.models import ( + DataKind, + LiveStrategyRun, + MarketDataset, + MarketDatasetVersion, + Strategy, + StrategyVersion, + TradingProject, +) +from control_plane.trading_studio.qualification import ( + Bar, + CalibrationMethod, + CostModel, + QualificationReplayV1, + ScenarioSpec, + calibrate_train_only, + qualification_scenario_catalog, +) +from control_plane.trading_studio.services import TradingStudioService + +BASE = datetime(2026, 1, 5, tzinfo=UTC) + + +def bar(day, open_, high, low, close, signal=None, context=(), reference=""): + return Bar(BASE + timedelta(days=day), open_, high, low, close, signal, context, reference) + + +def calibrated(bars, *, method=CalibrationMethod.RAW): + return calibrate_train_only( + bars, + method=method, + fold="fold-a", + train_start=BASE, + train_end=BASE + timedelta(days=1), + source_record_ids=("source-1", "source-2"), + source_combo="ohlcv+context", + percentile=50, + ) + + +def run(bars, scenario=None): + return QualificationReplayV1().run( + bars, + strategy="strategy-v1", + dataset="Cohort001", + fold="fold-a", + runner="test-runner", + scenario=scenario or ScenarioSpec("base", 100, 100), + calibration=calibrated(bars), + ) + + +def test_multibar_state_machine_emits_signal_entry_exit_and_ledger_directly(): + result = run( + [ + bar(0, 100, 101, 99, 100, 1), + bar(1, 100, 101, 99, 100, 2), + bar(2, 100, 102, 99, 101), + bar(3, 101, 103, 100, 102), + ] + ) + assert [event.event_type for event in result.events] == [ + "SIGNAL", + "ENTRY_QUEUED", + "ENTRY", + "EXIT", + ] + assert result.ledger[0].holding_bars == 1 + assert result.ledger[0].entry_bar == 2 + + +def test_same_bar_tp_sl_ambiguity_is_pessimistic_stop(): + result = run( + [bar(0, 100, 101, 99, 100, 1), bar(1, 100, 101, 99, 100, 2), bar(2, 100, 102, 98, 101)] + ) + assert result.ledger[0].exit_reason == "SL" + assert result.ledger[0].exit_execution_price == 99 + + +def test_delay_creates_natural_later_entry(): + result = run( + [ + bar(0, 100, 101, 99, 100, 1), + bar(1, 100, 101, 99, 100, 2), + bar(2, 100, 100, 99, 100), + bar(3, 100, 102, 99, 101), + ], + ScenarioSpec("delay", 100, 100, entry_delay_bars=2), + ) + assert result.ledger[0].entry_bar == 3 + + +def test_stop_width_changes_later_eligibility(): + bars = [ + bar(0, 100, 101, 99, 100, 1), + bar(1, 100, 101, 99, 100, 2), + bar(2, 100, 100.5, 98.5, 99), + bar(3, 99, 101, 98, 100, 2), + bar(4, 100, 102, 99, 101), + ] + narrow = run(bars, ScenarioSpec("narrow", 100, 100, cooldown_bars=1)) + wide = run(bars, ScenarioSpec("wide", 300, 100, cooldown_bars=1, max_holding_bars=3)) + assert len(narrow.ledger) == 2 + assert len(wide.ledger) == 1 + + +def test_costs_funding_and_ledger_reconcile(): + costs = CostModel("v9", 10, 20, 5, 5, 1, 0.5, 0.25) + result = run( + [bar(0, 100, 101, 99, 100, 1), bar(1, 100, 101, 99, 100, 2), bar(2, 100, 102, 99, 101)], + ScenarioSpec("costed", 100, 100, cost_model=costs), + ) + row = result.ledger[0] + assert row.net_pnl == pytest.approx( + row.gross_pnl - row.entry_commission - row.exit_commission - row.funding - row.other_cost + ) + assert row.entry_slippage > 0 and row.exit_slippage > 0 + + +def test_deq_uses_forward_path_not_trade_pnl(): + result = run( + [ + bar(0, 100, 101, 99, 100, 1), + bar(1, 100, 101, 99, 100, 2), + bar(2, 100, 100, 99, 100), + bar(3, 100, 110, 99, 109), + ] + ) + deq = result.ledger[0].deq + assert deq.return_1_bars_bps == 900 + assert deq.mfe_bps == 1000 + assert deq.time_to_positive_bars == 1 + assert deq.time_to_25_bps_bars == 1 + assert deq.time_to_50_bps_bars == 1 + assert deq.max_adverse_before_positive_bps == -100 + + +def test_deq_is_direction_correct_and_rescue_is_ledger_derived(): + result = run( + [ + bar(0, 100, 101, 99, 100, 1), + bar(1, 100, 101, 99, 100, -2), + bar(2, 100, 100.5, 98, 99), + bar(3, 99, 99.5, 95, 96), + ] + ) + deq = result.ledger[0].deq + assert deq.return_1_bars_bps == 400 + assert deq.mfe_bps == 500 + assert deq.mae_bps == -50 + assert result.rescue.trade_count == len(result.ledger) + assert result.rescue.win_count + result.rescue.loss_count == result.rescue.trade_count + assert result.rescue.net_pnl == result.net_pnl + assert result.rescue.commissions == result.commissions + + +def test_exact_named_scenario_catalog_and_round_trip_costs(): + catalog = qualification_scenario_catalog() + assert set(catalog) == { + "BASELINE", + "SLIPPAGE_ADVERSE_2BP", + "TOTAL_COST_6BP", + "TOTAL_COST_10BP", + "TOTAL_COST_15BP", + "PESSIMISTIC_SAME_BAR", + "ENTRY_DELAY_PLUS_ONE_BAR", + "WEEKDAYS_ONLY", + "ALL_DAYS", + "STOP_WIDTH_100", + "STOP_WIDTH_75", + "STOP_WIDTH_50", + "STOP_WIDTH_25", + } + assert catalog["SLIPPAGE_ADVERSE_2BP"].cost_model.nominal_round_trip_bps == 2 + assert catalog["TOTAL_COST_15BP"].cost_model.nominal_round_trip_bps == 15 + assert catalog["ENTRY_DELAY_PLUS_ONE_BAR"].entry_delay_bars == 2 + assert catalog["ALL_DAYS"].allow_weekend_entries is True + + +def test_batch_protocol_identity_is_an_optional_canary_input_and_persisted_snapshot(): + scenario = ScenarioSpec("batch", 100, 100) + identity = {"specimen_report_sha256": "1148d891" + "0" * 56} + + assert TradingStudioService.qualification_configuration(scenario) == { + "name": "batch", + "stop_loss_bps": 100, + "take_profit_bps": 100, + "entry_delay_bars": 1, + "cooldown_bars": 0, + "max_holding_bars": 1, + "allow_weekend_entries": False, + "same_bar_policy": "PESSIMISTIC_SL", + "cost_model": { + "version": "qualification-v1", + "entry_commission_bps": 0.0, + "exit_commission_bps": 0.0, + "entry_slippage_bps": 0.0, + "exit_slippage_bps": 0.0, + "funding_bps_per_bar": 0.0, + "entry_other_cost": 0.0, + "exit_other_cost": 0.0, + }, + } + snapshot = TradingStudioService.qualification_configuration( + scenario, protocol_identity=identity, require_protocol_identity=True + ) + assert snapshot["protocol_identity"] == identity + with pytest.raises(ValueError, match="requires a protocol identity"): + TradingStudioService.qualification_configuration( + scenario, require_protocol_identity=True + ) + + +def test_raw_calibration_has_no_holdout_leak_ab_equivalence(): + left = [bar(0, 10, 11, 9, 10, 1, (1,)), bar(1, 10, 11, 9, 10, 100, (100,))] + right = [bar(0, 10, 11, 9, 10, 1, (1,)), bar(1, 10, 11, 9, 10, -999, (-999,))] + assert calibrated(left).threshold == calibrated(right).threshold == 1 + + +def test_cohort_raw_calibration_retains_zero_signal_train_provenance_without_fabrication(): + bars = [ + bar(0, 100, 101, 99, 100, None, (1.0,), "train-0"), + bar(1, 100, 101, 99, 100, None, (2.0,), "train-1"), + bar(2, 100, 101, 99, 100, None, (3.0,), "replay-0"), + ] + calibration = calibrate_train_only( + bars, + method=CalibrationMethod.RAW, + fold="fold-a", + train_start=BASE, + train_end=BASE + timedelta(days=2), + source_record_ids=("frozen-member",), + source_combo="frozen-hs22-combo", + allow_empty_raw=True, + ) + result = QualificationReplayV1().run( + bars[2:], + strategy="strategy-v1", + dataset="Cohort001", + fold="fold-a", + runner="cohort_qualification_hyperscalper_001:v1", + scenario=ScenarioSpec("baseline", 100, 100), + calibration=calibration, + ) + + assert calibration.threshold == 0.0 + assert calibration.sample_count == 0 + assert calibration.source_combo == "frozen-hs22-combo" + assert calibration.input_hash + assert result.ledger == () + assert result.rescue.trade_count == 0 + assert result.rescue.net_pnl == 0 + + +def test_percentile_calibration_still_rejects_zero_qualifying_train_signals(): + with pytest.raises(ValueError, match="Train-only calibration"): + calibrate_train_only( + [bar(0, 100, 101, 99, 100)], + method=CalibrationMethod.PERCENTILE, + fold="fold-a", + train_start=BASE, + train_end=BASE + timedelta(days=1), + source_record_ids=("frozen-member",), + source_combo="frozen-hs22-combo", + percentile=50, + allow_empty_raw=True, + ) + + +def test_percentile_calibration_records_provenance_and_continuous_context(): + bars = [bar(0, 10, 11, 9, 10, 1, (0.1, 0.2)), bar(0, 10, 11, 9, 10, 3, (0.3, 0.4))] + value = calibrate_train_only( + bars, + method=CalibrationMethod.PERCENTILE, + fold="fold-a", + train_start=BASE, + train_end=BASE + timedelta(days=1), + source_record_ids=("a",), + source_combo="ohlcv+continuous", + percentile=100, + ) + assert value.threshold == 3 and value.input_hash and value.source_combo == "ohlcv+continuous" + + +def test_reference_mode_is_absent_and_scenario_names_are_required(): + assert not hasattr(QualificationReplayV1, "reference_mode") + with pytest.raises(ValueError, match="named"): + ScenarioSpec("", 100, 100) + with pytest.raises( + ValueError, + match="missing materialized strategy_version, dataset_version, bars, calibration", + ): + TradingStudioService().run_qualification_canary( + strategy_version=None, + dataset_version=None, + fold="fold-a", + scenario=ScenarioSpec("canary", 100, 100), + runner_name="runner", + bars=[], + calibration=None, + ) + + +def test_materialized_canary_persists_without_creating_live_run(): + project = Project.objects.create(name="Canary", goal="Test qualification persistence") + trading_project = TradingProject.objects.create( + project=project, + name="Canary Trading", + slug="canary-trading", + goal="Test qualification persistence", + ) + dataset = MarketDataset.objects.create( + trading_project=trading_project, + name="Materialized BTCUSDT", + kind=DataKind.OHLCV, + ) + dataset_version = MarketDatasetVersion.objects.create( + dataset=dataset, + version="frozen-v1", + reference="artifact://materialized.csv", + content_hash="a" * 64, + ) + strategy = Strategy.objects.create(trading_project=trading_project, name="HS22") + strategy_version = StrategyVersion.objects.create( + strategy=strategy, + version="frozen-v1", + genome={"combo": [1]}, + fingerprint="b" * 64, + ) + bars = [ + bar(0, 100, 101, 99, 100, 1), + bar(1, 100, 101, 99, 100, 2), + bar(2, 100, 102, 99, 101), + bar(3, 101, 103, 100, 102), + ] + + service = TradingStudioService() + run = service.run_qualification_canary( + strategy_version=strategy_version, + dataset_version=dataset_version, + fold="fold-a", + scenario=ScenarioSpec("baseline", 100, 100), + runner_name="test-runner", + bars=bars, + calibration=calibrated(bars), + ) + + assert run.replay_mode == "CANARY_ONLY" + assert run.ledger_rows.count() == 1 + assert LiveStrategyRun.objects.count() == 0 + + zero_bars = [bar(0, 100, 101, 99, 100), bar(1, 100, 101, 99, 100)] + zero_run = service.run_qualification_canary( + strategy_version=strategy_version, + dataset_version=dataset_version, + fold="fold-zero", + scenario=ScenarioSpec("zero-trade", 100, 100), + runner_name="test-runner", + bars=zero_bars, + calibration=calibrate_train_only( + zero_bars, + method=CalibrationMethod.RAW, + fold="fold-zero", + train_start=BASE, + train_end=BASE + timedelta(days=1), + source_record_ids=("frozen-member",), + source_combo="frozen-hs22-combo", + allow_empty_raw=True, + ), + ) + + assert zero_run.ledger_rows.count() == 0 + assert zero_run.summary["ledger_count"] == 0 + assert zero_run.summary["rescue"]["trade_count"] == 0 + assert zero_run.summary["rescue"]["net_pnl"] == 0 diff --git a/tools/batch01_native_mismatch_report.py b/tools/batch01_native_mismatch_report.py new file mode 100644 index 0000000..28989d3 --- /dev/null +++ b/tools/batch01_native_mismatch_report.py @@ -0,0 +1,232 @@ +"""Generate an exact diagnostic for frozen Batch01 native/oracle mismatches. + +This is diagnostic-only: it evaluates the recovered native formulas without +altering their arithmetic or the frozen oracle artifacts. +""" + +from __future__ import annotations + +import json +import math +from pathlib import Path +from typing import Any + +import numba as nb +import numpy as np + +from control_plane.trading_studio.indicators.batch01_native_parity import ( + BATCH01_OUTPUTS, + BATCH01_REQUEST, + _load_ohlcv, + _require_frozen_artifacts, +) +from control_plane.trading_studio.indicators.historical_band_channel import ( + _sma, + evaluate_band_channel, +) + +ROOT = Path(__file__).resolve().parents[1] +JSON_PATH = ROOT / "batch01_native_mismatch_report.json" +MARKDOWN_PATH = ROOT / "batch01_native_mismatch_root_cause.md" +_SIGN = 1 << 63 +_MASK = (1 << 64) - 1 + + +def _bits(value: float) -> int: + return int(np.asarray(value, dtype=np.float64).view(np.uint64)) + + +def _ordered_bits(value: float) -> int: + bits = _bits(value) + return (~bits & _MASK) if bits & _SIGN else bits | _SIGN + + +def _float(value: float) -> dict[str, Any]: + bits = _bits(value) + return {"decimal": float(value), "hex": float(value).hex(), "bits": f"0x{bits:016x}"} + + +def _ulp(expected: float, actual: float) -> dict[str, int]: + signed = _ordered_bits(expected) - _ordered_bits(actual) + return {"signed": signed, "absolute": abs(signed)} + + +def _band_intermediate(close: np.ndarray, index: int, period: int) -> dict[str, Any]: + mean = _sma(close, period)[index] + variance_sum = sum( + (close[item] - mean) ** 2 for item in range(index - period + 1, index + 1) + ) + variance = variance_sum / (period - 1) + return { + "window_start": index - period + 1, + "window_end": index, + "mean": _float(mean), + "variance_sum": _float(variance_sum), + "sample_variance": _float(variance), + "sample_stddev": _float(math.sqrt(variance)), + } + + +@nb.njit(cache=True) +def _recovered_band_intermediate( + close: np.ndarray, index: int, period: int +) -> tuple[float, float, float, float]: + """Execute the recovered Numba arithmetic solely to expose its intermediates.""" + mean_sum = 0.0 + for item in range(period): + mean_sum += close[item] + for item in range(period, index + 1): + mean_sum += close[item] - close[item - period] + mean = mean_sum / period + variance_sum = 0.0 + for item in range(index - period + 1, index + 1): + variance_sum += (close[item] - mean) ** 2 + variance = variance_sum / (period - 1) + return mean, variance_sum, variance, math.sqrt(variance) + + +def _recovered_intermediate(close: np.ndarray, index: int, period: int) -> dict[str, Any]: + mean, variance_sum, variance, standard_deviation = _recovered_band_intermediate(close, index, period) + return { + "mean": _float(mean), + "variance_sum": _float(variance_sum), + "sample_variance": _float(variance), + "sample_stddev": _float(standard_deviation), + } + + +def _threshold(close: float, expected: float, actual: float) -> dict[str, Any]: + expected_above = close > expected + actual_above = close > actual + return { + "close": _float(close), + "oracle_close_minus_band": _float(close - expected), + "native_close_minus_band": _float(close - actual), + "oracle_close_above_band": expected_above, + "native_close_above_band": actual_above, + "decision_changed": expected_above != actual_above, + "close_to_oracle_band_ulps": _ulp(close, expected)["absolute"], + "close_to_native_band_ulps": _ulp(close, actual)["absolute"], + } + + +def _request_id(indicator_id: int, period: int, p1: float) -> str: + p1_text = str(int(p1)) if p1.is_integer() else str(p1) + return f"batch01_{indicator_id}_{period}_{p1_text}" + + +def build_report() -> dict[str, Any]: + request, _ = _require_frozen_artifacts() + close, high, low, volume = _load_ohlcv() + actual_by_id: dict[str, np.ndarray] = {} + request_by_id = {item["request_id"]: item for item in request["requests"]} + for item in request["requests"]: + actual_by_id[item["request_id"]] = evaluate_band_channel( + int(item["indicator_id"]), close, high, low, volume, int(item["period"]), float(item["p1"]) + ) + + variants: list[dict[str, Any]] = [] + with np.load(BATCH01_OUTPUTS) as oracle: + for request_id, item in request_by_id.items(): + expected = oracle[request_id] + actual = actual_by_id[request_id] + mismatch_indexes = np.flatnonzero(~((expected == actual) | (np.isnan(expected) & np.isnan(actual)))) + variant: dict[str, Any] = { + "request_id": request_id, + "indicator_id": item["indicator_id"], + "period": item["period"], + "p1": item["p1"], + "classification": "exact" if not len(mismatch_indexes) else "numeric_evaluation_order_drift", + "mismatch_count": int(len(mismatch_indexes)), + "mismatches": [], + } + for index in mismatch_indexes: + expected_value, actual_value = float(expected[index]), float(actual[index]) + detail: dict[str, Any] = { + "index": int(index), + "oracle": _float(expected_value), + "native": _float(actual_value), + "absolute_error": _float(abs(expected_value - actual_value)), + "ulp": _ulp(expected_value, actual_value), + "threshold_sensitivity": _threshold(float(close[index]), expected_value, actual_value), + } + if int(item["indicator_id"]) in {17, 18}: + period, p1 = int(item["period"]), float(item["p1"]) + upper_id, lower_id = _request_id(17, period, p1), _request_id(18, period, p1) + oracle_upper, oracle_lower = float(oracle[upper_id][index]), float(oracle[lower_id][index]) + native_upper = float(actual_by_id[upper_id][index]) + native_lower = float(actual_by_id[lower_id][index]) + oracle_center = (oracle_upper + oracle_lower) / 2.0 + native_center = (native_upper + native_lower) / 2.0 + oracle_half_width = (oracle_upper - oracle_lower) / 2.0 + native_half_width = (native_upper - native_lower) / 2.0 + detail["native_formula_intermediate"] = _band_intermediate(close, int(index), period) + detail["recovered_numba_intermediate"] = _recovered_intermediate( + close, int(index), period + ) + detail["upper_lower_symmetry"] = { + "oracle_center": _float(oracle_center), + "native_center": _float(native_center), + "center_error": _float(oracle_center - native_center), + "oracle_half_width": _float(oracle_half_width), + "native_half_width": _float(native_half_width), + "half_width_error": _float(oracle_half_width - native_half_width), + "upper_error": _float(oracle_upper - native_upper), + "lower_error": _float(oracle_lower - native_lower), + } + variant["mismatches"].append(detail) + variants.append(variant) + + failures = [variant for variant in variants if variant["mismatch_count"]] + return { + "artifact": "BATCH01_NATIVE_MISMATCH_REPORT_V1", + "scope": "frozen batch01 oracle NPZ/request/CSV against native recovered band code", + "formula_mutations": False, + "variant_count": len(variants), + "failed_variant_count": len(failures), + "failed_value_count": sum(item["mismatch_count"] for item in failures), + "classification": "numeric_evaluation_order_drift_only" if failures else "exact_parity", + "variants": variants, + } + + +def _markdown(report: dict[str, Any]) -> str: + failures = [item for item in report["variants"] if item["mismatch_count"]] + lines = [ + "# Batch01 Native Mismatch Root Cause", + "", + "## Classification", + "", + f"`{report['classification']}`: {report['failed_value_count']} bitwise mismatches in " + f"{report['failed_variant_count']} of {report['variant_count']} requests.", + "", + "## Evidence", + "", + "- All failures are Bollinger pairs: 17 (upper) and 18 (lower).", + "- Every failure has the same index and parameter pair in the opposite band.", + "- The JSON report records the oracle/native IEEE-754 bit patterns, signed ULP delta, native rolling mean/sample standard deviation, and paired-band center/half-width decomposition.", + "- Threshold comparisons (`close > band`) are unchanged at every failed value.", + "", + "## Root Cause", + "", + "The recovered Numba source and native port have bit-identical rolling means at every failed bar, but the Python generator reduction and the recovered scalar Numba variance loop differ by one or two low-order bits. Their compiled/CPython `sqrt` results can add a further low-order difference. The resulting standard-deviation rounding propagates as an equal-and-opposite upper/lower half-width shift. The evidence rules out a formula, parameter, warmup, or band-sign error.", + "", + "## Failed Requests", + "", + ] + for item in failures: + indexes = ", ".join(str(detail["index"]) for detail in item["mismatches"]) + ulps = ", ".join(str(detail["ulp"]["signed"]) for detail in item["mismatches"]) + lines.append(f"- `{item['request_id']}`: indexes {indexes}; signed ULPs {ulps}.") + lines.append("") + return "\n".join(lines) + + +def main() -> None: + report = build_report() + JSON_PATH.write_text(json.dumps(report, indent=2, allow_nan=False) + "\n", encoding="utf-8") + MARKDOWN_PATH.write_text(_markdown(report), encoding="utf-8") + + +if __name__ == "__main__": + main() diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..a885819 --- /dev/null +++ b/uv.lock @@ -0,0 +1,1390 @@ +version = 1 +revision = 3 +requires-python = ">=3.12" + +[[package]] +name = "annotated-types" +version = "0.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5f/56/a8120250d128bed162cd73c76d45f6ef9991f3e068f62a8ee060afa3104a/annotated_types-0.8.0.tar.gz", hash = "sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7", size = 15893, upload-time = "2026-07-23T20:16:13.995Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/91/8acff4f5e50511b911bbccb72b8628a49c68ce14148cd9f6431094859a90/annotated_types-0.8.0-py3-none-any.whl", hash = "sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0", size = 13427, upload-time = "2026-07-23T20:16:12.938Z" }, +] + +[[package]] +name = "anyio" +version = "4.14.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/cc/a381afa6efea9f496eff839d4a6a1aed3bfafc7b3ab4b0d1b243a12573dd/anyio-4.14.2.tar.gz", hash = "sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f", size = 260176, upload-time = "2026-07-12T20:29:07.082Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/35/f2287558c17e29fafc8ef3daf819bb9834061cfa43bff8014f7df7f63bdc/anyio-4.14.2-py3-none-any.whl", hash = "sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494", size = 125813, upload-time = "2026-07-12T20:29:05.763Z" }, +] + +[[package]] +name = "artifex" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "django" }, + { name = "langgraph" }, + { name = "numba" }, + { name = "numpy" }, + { name = "psycopg", extra = ["binary"] }, + { name = "structlog" }, +] + +[package.optional-dependencies] +dev = [ + { name = "pyarrow" }, + { name = "pytest" }, + { name = "pytest-django" }, + { name = "ruff" }, +] + +[package.metadata] +requires-dist = [ + { name = "django", specifier = ">=5.1,<6.0" }, + { name = "langgraph", specifier = ">=0.2,<0.3" }, + { name = "numba", specifier = ">=0.60,<1.0" }, + { name = "numpy", specifier = ">=2.0,<3.0" }, + { name = "psycopg", extras = ["binary"], specifier = ">=3.2,<4.0" }, + { name = "pyarrow", marker = "extra == 'dev'", specifier = ">=25.0.1" }, + { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.3,<9.0" }, + { name = "pytest-django", marker = "extra == 'dev'", specifier = ">=4.9,<5.0" }, + { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.8,<1.0" }, + { name = "structlog", specifier = ">=24.4,<25.0" }, +] +provides-extras = ["dev"] + +[[package]] +name = "asgiref" +version = "3.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e6/26/3b59f2bdae5f640389becb1f673cded775287f5fc4f816309d9ca9a3f93d/asgiref-3.12.1.tar.gz", hash = "sha256:59dcb51c272ad209d59bed5708a64a333083e86017d7fcdd67498eeab7784340", size = 42378, upload-time = "2026-07-14T09:56:18.087Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/1b/54f4ad77cd8a584fa70746c47df988e002cf1ee1eba43364d46f87803647/asgiref-3.12.1-py3-none-any.whl", hash = "sha256:fe386d1c2bff7259ea95929266d12a8cf9a8b5a1c2598402967d8792e7a7c094", size = 25478, upload-time = "2026-07-14T09:56:16.926Z" }, +] + +[[package]] +name = "certifi" +version = "2026.7.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a3/c2/24167ea9858356b47a87a50d39908bfdb72ceeefe0041586e704e5376b3a/certifi-2026.7.22.tar.gz", hash = "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55", size = 138112, upload-time = "2026-07-22T03:35:12.644Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/a7/71ac2cff56fec219ed242bb11b8efb69fcc4bec75db06fb7bfe35de520e6/certifi-2026.7.22-py3-none-any.whl", hash = "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", size = 136983, upload-time = "2026-07-22T03:35:11.276Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e5/3f/143b048436775b0f76ac3eec145c019e8173ccc2885c8f20319b996d5e83/charset_normalizer-3.5.1.tar.gz", hash = "sha256:6117b84ea48435e5356dc737f5121485c30920ba43375fa7b434fd753df0eac3", size = 171764, upload-time = "2026-08-15T08:20:44.807Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/30/27/78873dc8b6a56357517b74b6bb9568b80450e7bb4f6ef7e3fa9d22aa0bd7/charset_normalizer-3.5.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:5b6d1386bf0096d26d3a863dc0a487a5b4eb9aa93cf5ba69683d29dde6b9d60f", size = 344456, upload-time = "2026-08-15T08:17:10.072Z" }, + { url = "https://files.pythonhosted.org/packages/9a/4c/be49ada26b1f0232d57aa89bbebf997a5cc2332a5616b6eca26ff680044d/charset_normalizer-3.5.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4582c27e8c889d64811987b5967fbd3ae0c823fe1fd933b543d55ac20bb475fa", size = 238530, upload-time = "2026-08-15T08:17:11.563Z" }, + { url = "https://files.pythonhosted.org/packages/76/84/6f1290fa07ae6978d3960caa3eb1b8019bf9284ab7c2297b00c099ef4250/charset_normalizer-3.5.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:1d1c7a53a6c2103925cdd6d7229f8c567379f211c869793df679f2e9f738c369", size = 230200, upload-time = "2026-08-15T08:17:12.919Z" }, + { url = "https://files.pythonhosted.org/packages/e7/a0/47b18adeed31c8f16ba9700f32c1b18594cfa09f47eb672a488c273c22bf/charset_normalizer-3.5.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e6621fb2a4988d6e53eedc455e5903e2679f3967b8acb3d639f1b63c14a2e893", size = 262222, upload-time = "2026-08-15T08:17:14.571Z" }, + { url = "https://files.pythonhosted.org/packages/38/fe/341861ac118dae06f3ec0eb487488af52128f2ef2faf0b11003944d22259/charset_normalizer-3.5.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7c0c10730342b0c9b35dd1d619beb8214e520bd96a1f870f452680b238aab3e0", size = 258951, upload-time = "2026-08-15T08:17:16.158Z" }, + { url = "https://files.pythonhosted.org/packages/6f/89/bb5108dc6c3651dca963f2b0a3ba19bbcb370c94e1b6d3e0e844a58e6dca/charset_normalizer-3.5.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b9af956078716df40d985fb0dfeb2c2120c5ca92ba4ff4b388acfd01cdc14d08", size = 248801, upload-time = "2026-08-15T08:17:17.683Z" }, + { url = "https://files.pythonhosted.org/packages/b1/ba/ef83ae3aca816393decfa3530976f38a79812d707b80b580ac33b83f9877/charset_normalizer-3.5.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f9f8405c2c758532c74fed975dbee57be1f31a6e865c031870c79a6ed3212ada", size = 244070, upload-time = "2026-08-15T08:17:19.191Z" }, + { url = "https://files.pythonhosted.org/packages/f6/0b/c5292a2462d69b7378ea89793bbb5b2b6fcf6f7dd6d1667f9619094ad553/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:96fef3e886d6a9874b14f27fc193fbdc69d5d8035783d86aa4e1cea594e695f9", size = 240110, upload-time = "2026-08-15T08:17:20.547Z" }, + { url = "https://files.pythonhosted.org/packages/46/22/111e5be3b740d5c2a5bfcedb3d237b6591e5c2e82ae9d6ffcb121fe0909c/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5d8531a6569d025f68e2321e7638fb7978f23db58e5f69f56913837aae03816e", size = 232836, upload-time = "2026-08-15T08:17:21.895Z" }, + { url = "https://files.pythonhosted.org/packages/f9/d2/d2aad6fe0dbb44b194bf3becb60f5a0ac48446ade999a47fe7bb41eb09a7/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:aae2ee51122d3ae968a3837d97dc24a0aeebb0dea23694422cd172bd30017cd6", size = 262712, upload-time = "2026-08-15T08:17:23.727Z" }, + { url = "https://files.pythonhosted.org/packages/35/5a/337e4663a5eae6de99db940ee8066d4145caafb61327db62deda15313cce/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7235dc28fc6dd9d832ac7c7bce95367dedb85929f17368a0c2bee1e080b9acbf", size = 242977, upload-time = "2026-08-15T08:17:25.157Z" }, + { url = "https://files.pythonhosted.org/packages/ca/85/f82f8a92e31c7519410e2e1afdc630f28ec47490ce2c09a11c1a43cbb459/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4abdc5f9ad448c1ecbfae2974b820535d6bc6e7eef63babbab3d81cf46968c71", size = 260207, upload-time = "2026-08-15T08:17:26.602Z" }, + { url = "https://files.pythonhosted.org/packages/b7/52/643d11ffd60e9ac2fd1fb87e167a19285b9eefeff4a40e63c87cbfbeab36/charset_normalizer-3.5.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba501e667c17d8411f98e67a022d9604ef179aff0e459b7e292c796837c13573", size = 250562, upload-time = "2026-08-15T08:17:27.971Z" }, + { url = "https://files.pythonhosted.org/packages/62/16/46556278c2168d12df9da7fede5dc6fc70e60301b26a82bbeec238c9cfe3/charset_normalizer-3.5.1-cp312-cp312-win32.whl", hash = "sha256:cfa1c0cc3a8f9f53f1243a5a99ac36fd003880199383b37672e86ddda9cb07e2", size = 178507, upload-time = "2026-08-15T08:17:29.277Z" }, + { url = "https://files.pythonhosted.org/packages/9d/7a/4c6c298171e6b3e745633180ff59350fc0ca0db1ffd28df1e369e0579f71/charset_normalizer-3.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:3617ac3cfd8b9888f145ad89dd6e692285834b0201c6074a5eeaad3fd4d668c2", size = 200551, upload-time = "2026-08-15T08:17:30.668Z" }, + { url = "https://files.pythonhosted.org/packages/cd/d7/eb95a042f0dd22e304b0b6472b154f3546a1a039a9ee89ccb2a7f61591fc/charset_normalizer-3.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:88e85ab89cb822c1e635f51d6d32e488f94e002e70e2f492bdb8b945543f345a", size = 180700, upload-time = "2026-08-15T08:17:32.028Z" }, + { url = "https://files.pythonhosted.org/packages/bc/61/2cb6ad133dbbb449fa2d37ccae973232f4827e799af258d15e589a3d1e9e/charset_normalizer-3.5.1-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:4f298bdadb8f0b9e5672877f647d1be9373ef5320c9e2f049795e26cad28b6a9", size = 211584, upload-time = "2026-08-15T08:17:33.597Z" }, + { url = "https://files.pythonhosted.org/packages/18/57/a305c968be1ca13f3dd1b32f445877e97addf55d80b65c7cb35fac82b777/charset_normalizer-3.5.1-cp313-cp313-android_24_x86_64.whl", hash = "sha256:88ca277405c2d3b71c4e1c2ee0e7966e807bcba86a69d11e19ba199d18ae4491", size = 223359, upload-time = "2026-08-15T08:17:35.022Z" }, + { url = "https://files.pythonhosted.org/packages/09/0a/d3646670292ce8d8f8cc11ac067d44885e697a5591f57a9221128da5e7b3/charset_normalizer-3.5.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:9362dd90aa7dab48c0054a21187791ccf05473f7dba5d92b8033ae62164675e7", size = 194464, upload-time = "2026-08-15T08:17:36.452Z" }, + { url = "https://files.pythonhosted.org/packages/de/93/d51ec556e01042fed6f993ea859311bc7917b466684182fbbceb6ca24762/charset_normalizer-3.5.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:977cdbd483a9cff38179bea4fd754289a6f2195c7abd414aba85410b3e66cc5e", size = 197676, upload-time = "2026-08-15T08:17:37.819Z" }, + { url = "https://files.pythonhosted.org/packages/a4/a0/562247944386f7d4ef94467e84876600cc1e0f1b93239aaa9213d2bc3cbd/charset_normalizer-3.5.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e90251c0c7bdd54a100a0dce3c07b7e637278c93af29dbf78ebb89a58c4bac7d", size = 340473, upload-time = "2026-08-15T08:17:39.303Z" }, + { url = "https://files.pythonhosted.org/packages/31/e7/1d994be1b93d41e9502b8b0460eaa88a1dd8df335df415db87d6c3e91ab2/charset_normalizer-3.5.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94d78ecec2605a8d0398b0f365d5f12a63248438516f5dac536a5eff7337df4a", size = 240156, upload-time = "2026-08-15T08:17:40.66Z" }, + { url = "https://files.pythonhosted.org/packages/09/53/27923ce5cc6cbccb832037b27dca98882d9c53e9b69e866bbbef4aae7fc8/charset_normalizer-3.5.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d59b75732e9b6f27388e10c14b0259cc5f2e48c78627d185e6a177b58ad3cffe", size = 228246, upload-time = "2026-08-15T08:17:42.003Z" }, + { url = "https://files.pythonhosted.org/packages/ce/48/5a97e84d63af1d55c07439cb80e56d99a8efb4295700eb4e18c0d1615d2c/charset_normalizer-3.5.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0d929fc574b4d6fd9e7c0f5c2ede8716a41911923aa7fa5fce38e0818aa4a1ac", size = 263660, upload-time = "2026-08-15T08:17:43.627Z" }, + { url = "https://files.pythonhosted.org/packages/7a/c2/071575791dcc88316c0a9a65ce38897a82e4cfe4a325f0f7fe1b1ac47bcf/charset_normalizer-3.5.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:394fea06235c8543390050ed5f529187074b029fb027213f6c46ac11ab5d950e", size = 260354, upload-time = "2026-08-15T08:17:45.094Z" }, + { url = "https://files.pythonhosted.org/packages/fb/af/63240b0c0248c075c2535a1f1bd992821d8251b9f173abc13329661d09e4/charset_normalizer-3.5.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62b55f6722735a6c472f88361cde6640608773d9443cebdbb51abf436a1fcdd3", size = 250638, upload-time = "2026-08-15T08:17:46.496Z" }, + { url = "https://files.pythonhosted.org/packages/4d/66/70dfad64f15be09c15ccfee81330a7e515895dbe296dd23114e9a231268a/charset_normalizer-3.5.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa48b1b63d639f9483e0633e092f5851e2348c352f1f9bb6c8182f87884ef876", size = 244583, upload-time = "2026-08-15T08:17:47.963Z" }, + { url = "https://files.pythonhosted.org/packages/c0/24/ef36367d38b9ddd4bccbf72888c342e8de1f5ae506fa0b2dcf970e2732a1/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c71fb0d56c920c269cd3e2e3fe7c610e3f1fdb21a6ce60efa6430ff63676cea6", size = 242038, upload-time = "2026-08-15T08:17:49.481Z" }, + { url = "https://files.pythonhosted.org/packages/db/ab/55e683ba0fff2e43adafc10daa3001eac90fdaa419a97227d5a7067eedde/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:485a0d363cafefcd2538a73c7c838daa2035f09b2c9f9b5e3133f80c6aeb84c2", size = 233677, upload-time = "2026-08-15T08:17:50.845Z" }, + { url = "https://files.pythonhosted.org/packages/bd/67/0f40eaf8d1b6e7cf15e82382a2965efaca787fc1c2794b7021d37aaf5036/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c0ea61a470e070686aa30892fed79e297d2c8d0ab46b8bcdf027d38c51da591", size = 264491, upload-time = "2026-08-15T08:17:52.61Z" }, + { url = "https://files.pythonhosted.org/packages/5c/64/12b4c2a11ee8df4fcc518c78b0d93e3a92bd3d5253d1617ce74ff0e8c7ef/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:90b7481fb62fbe172c558bc6fd1c4c98d82004a54a7551f20e11ac9bf0b8708c", size = 245196, upload-time = "2026-08-15T08:17:54.023Z" }, + { url = "https://files.pythonhosted.org/packages/37/2e/651d910af6d0fba325eee1cda37ec5443462ed25360e666c144166eb6091/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:35fe081843b35aad20ffeccec3eeffbe637b15d14f3fb22cc1b59cd8ec17e93c", size = 261660, upload-time = "2026-08-15T08:17:55.491Z" }, + { url = "https://files.pythonhosted.org/packages/90/c6/b09e05e6db7f64338e0dc067c79577b1138da86c1e38369096851d96be88/charset_normalizer-3.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fd0350afdc3aabd5576f60ea109228bd5538139713c7b094c5cd27c73a98bc6f", size = 252618, upload-time = "2026-08-15T08:17:57.025Z" }, + { url = "https://files.pythonhosted.org/packages/76/4e/362d4f9fdcdf5556fb2aa3ce7d4a58ebce03ed1ff03aa1d9aca8d02f13f3/charset_normalizer-3.5.1-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:9d9a0dc7cbe9bec24c3f767c9122c41fe5a1bc43f47cd099d00d393e09769de4", size = 140362, upload-time = "2026-08-15T08:17:58.425Z" }, + { url = "https://files.pythonhosted.org/packages/b4/d4/703be739b26acce318bd29eb3b25b7209e1b1f527f9eae3d1f1f01fdde2b/charset_normalizer-3.5.1-cp313-cp313-win32.whl", hash = "sha256:d63600d620ad0064c3a748b950ac5ea38a80190e5498532efefa4b7b3f1da1f3", size = 177755, upload-time = "2026-08-15T08:18:00.037Z" }, + { url = "https://files.pythonhosted.org/packages/8a/33/56d97ade41c8db611e727168c52ae46c9224c362ec28d4b65d7e9869e8da/charset_normalizer-3.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:aea996a6aba25260827c9ea511d1addfde2da9eb686ac961838509086188b7e6", size = 199295, upload-time = "2026-08-15T08:18:01.506Z" }, + { url = "https://files.pythonhosted.org/packages/5b/75/5b20dd1e6573a01a08158fe104104fa2c8abf941745596954185726cd46c/charset_normalizer-3.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:fd0a274c0e5f9a21565cd9d3dd749b61f96b7aa1e20a93aa1ba4029518f2e5c0", size = 179856, upload-time = "2026-08-15T08:18:02.929Z" }, + { url = "https://files.pythonhosted.org/packages/29/cd/2b812ce5e888f1ce69a5350281e58aab07ae64a958ecae8912f30865718e/charset_normalizer-3.5.1-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:774d157f112367ff4abd29019f38f023c24e00e56edc7829c20e358a5a913ad8", size = 212318, upload-time = "2026-08-15T08:18:04.403Z" }, + { url = "https://files.pythonhosted.org/packages/9e/4a/a6ee107430768a5334e6d63f31f148a04a1a491ef161a1ac9415a73f2fa8/charset_normalizer-3.5.1-cp314-cp314-android_24_x86_64.whl", hash = "sha256:26422d45fd13551cf564c58932f7d72b4f58b93b0fcf18c35ba6be12b46bb102", size = 224897, upload-time = "2026-08-15T08:18:05.997Z" }, + { url = "https://files.pythonhosted.org/packages/c3/d9/35ae3f64f29d0179c35c3baefe575904df2913dde519129c7f75995a2b1d/charset_normalizer-3.5.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:09a7bba9f739468c8e78c36a75c33768e53cb1959fc638f510454c14683f00d5", size = 194848, upload-time = "2026-08-15T08:18:07.397Z" }, + { url = "https://files.pythonhosted.org/packages/74/76/f2fc7380f056cc273a53af37f50d08ad54b2c59f61078f31432edcf1c2bd/charset_normalizer-3.5.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:4c9548dc78002099910abaebc0a72ac58b7d30931869e0351c09b507dff4ece3", size = 198163, upload-time = "2026-08-15T08:18:08.989Z" }, + { url = "https://files.pythonhosted.org/packages/e9/40/095ce62fa078483cccc1fa2b36e6bc9580b85422a20ee9f925341c50e44f/charset_normalizer-3.5.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c428c6c31eb5f4277d7f8eccaf767fbd548ddd5ce3c8b4f4cbbfab3d96b5904c", size = 341823, upload-time = "2026-08-15T08:18:10.458Z" }, + { url = "https://files.pythonhosted.org/packages/f1/5a/0e58b1c04a1596e0256f407274a92d5fb2ee21324409d1fab1da48a65b5b/charset_normalizer-3.5.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2f06b7eae9dbe77fe1d644ca244dad508de8d302870a43f3c559b521270938a0", size = 242458, upload-time = "2026-08-15T08:18:11.989Z" }, + { url = "https://files.pythonhosted.org/packages/22/95/b4618ce912e6db0b1aae89ba788e38e8a7eba0f3025cc66e8c0699f977b2/charset_normalizer-3.5.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6b7430cf5728e68f6c462254009a6ef4086e1bea43cf2f57aa9c55fb4f50ff96", size = 226717, upload-time = "2026-08-15T08:18:13.401Z" }, + { url = "https://files.pythonhosted.org/packages/8a/76/c681192bbda3d55356db5dadd64381d5202b37c6b598fcda5282e88b5d3d/charset_normalizer-3.5.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab743e9bc90c1f73552ec33e10e3331315acd2c397b36065b591b0181de533cc", size = 266111, upload-time = "2026-08-15T08:18:14.961Z" }, + { url = "https://files.pythonhosted.org/packages/88/be/55127bfca72c0cff6c022488d140d7c5b04c771e3b72e9bdb4836d54979d/charset_normalizer-3.5.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6f7deae3feb4edfa2efaf7c574fe88cbf055038a6abdb40188e4fff66d5699f", size = 263128, upload-time = "2026-08-15T08:18:16.515Z" }, + { url = "https://files.pythonhosted.org/packages/e0/91/39c3af510b0aa32bbda03374259200f28430febfd1bf5e511fe765282ce5/charset_normalizer-3.5.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15f024313246a4ed976c60f440bb8d257815513a681d212ff74fd46f7d715a90", size = 251240, upload-time = "2026-08-15T08:18:18.127Z" }, + { url = "https://files.pythonhosted.org/packages/1c/a5/cbe418bbc6ecdfc3e05a0116002897c4b403a5e838d697e64c78e9f0190d/charset_normalizer-3.5.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:823f82903d189af463d7df250ef1f7f696f3cee08cc8d91deb565e8d425f6506", size = 245282, upload-time = "2026-08-15T08:18:19.625Z" }, + { url = "https://files.pythonhosted.org/packages/cc/a4/689bb42e8e7cd492f3cb64907c6bc00ad247ec9a3628cd3f8eed126e8ae1/charset_normalizer-3.5.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:01e93745f7f219b703b60ba7afead36cfc4242782be5af484673fc500df12da5", size = 244597, upload-time = "2026-08-15T08:18:21.121Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ce/9962938e179cf9f699d3f1e7b3114b5d7642dee6a893745229f9dd04f274/charset_normalizer-3.5.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:329fc3ccb63ad22d867d84c2adea759a64079a37ba4a343433b02c7a2816871e", size = 231376, upload-time = "2026-08-15T08:18:22.57Z" }, + { url = "https://files.pythonhosted.org/packages/85/54/46000450ada53bd9eac5429a2c8c54cd2d9b39c0c255f229aea9af0948a5/charset_normalizer-3.5.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:bb57753e36e4855b8ca375069482250a6246372331a3e4f3407eaebb007443f5", size = 266715, upload-time = "2026-08-15T08:18:24.235Z" }, + { url = "https://files.pythonhosted.org/packages/3d/bb/618749d70f792b44252a777bf89bfb86823b9bbc1ea13fe8ce759b07f38a/charset_normalizer-3.5.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fce8cbd4997efeb450bd298b54f755dcdff18d496f7a5ddbb4867c6d7c88fdc3", size = 245848, upload-time = "2026-08-15T08:18:25.726Z" }, + { url = "https://files.pythonhosted.org/packages/7e/3f/ffb64458527c7668031d5eb095d978de561958dc9f5b53f8e488a533e603/charset_normalizer-3.5.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:6c9cdde8becb25a7fde49924511aa2644d6f8081cc8df8e9452724303348d8e3", size = 264521, upload-time = "2026-08-15T08:18:27.193Z" }, + { url = "https://files.pythonhosted.org/packages/4f/ab/74a55fd803916a35ac461daf002708191aac19b546b80dc8cabfedc63d98/charset_normalizer-3.5.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9ac4444d8d4fd4c4bd08bf451ed3167aa9e7ec6cdb41b648794f1d1103652e36", size = 253054, upload-time = "2026-08-15T08:18:28.568Z" }, + { url = "https://files.pythonhosted.org/packages/a0/2a/6a9034b7d3c60b17499afb482df5878bf9fa20b50cc3887d5ef017a833db/charset_normalizer-3.5.1-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:f03ac127268b43ef4fe9e6ab6794a6794b49485a0cc0c1db79876d2f33f75bc7", size = 140580, upload-time = "2026-08-15T08:18:30.214Z" }, + { url = "https://files.pythonhosted.org/packages/f3/46/1d362e1a00d035d66b9869e1281eee115907f7e390a16a07824ab5737360/charset_normalizer-3.5.1-cp314-cp314-win32.whl", hash = "sha256:1f5883d77fd409a261abb5dc8ccbe335720d798b1de4abb3b1d47ccbbc76b53b", size = 180325, upload-time = "2026-08-15T08:18:31.877Z" }, + { url = "https://files.pythonhosted.org/packages/7a/7c/4938c329b6a9d446f6a59aa2092ff7118f274209b5ed0e26893d1d30a63c/charset_normalizer-3.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:c658c50ac0c98cd755a2dd50b7977d3bca7df401dcc47fbdfa87db53ef7d4e8b", size = 204175, upload-time = "2026-08-15T08:18:33.466Z" }, + { url = "https://files.pythonhosted.org/packages/ac/33/eeb384dbd8dec570661354592f4f2e1b2fcc92585624d146a000caf53841/charset_normalizer-3.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:4bea7f8ebe90bbd7f0e4a2de42ca6924ba23e3e76418c408ff82f1d46fabd687", size = 184123, upload-time = "2026-08-15T08:18:34.913Z" }, + { url = "https://files.pythonhosted.org/packages/1c/6c/c73fa9d5a85f6ab05395de61c5f6984e0a9ff40bb5ff888d46dff02526c6/charset_normalizer-3.5.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:fbc597639158fd7c14d55e808718848319540f51b0e6746e3eefa59723a4a348", size = 381682, upload-time = "2026-08-15T08:18:36.349Z" }, + { url = "https://files.pythonhosted.org/packages/30/c7/63565f860921457feba93bae6c86fb7746deb4cffeed2f375cb845318146/charset_normalizer-3.5.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e71c909f353863b2b89c83de2ebed71ea6d0df8a6ef65a128193c5e650766bef", size = 240826, upload-time = "2026-08-15T08:18:37.887Z" }, + { url = "https://files.pythonhosted.org/packages/06/ae/7ae8807410dfa33f8e6f1715740adeaafa8a816cc4cb33508f54b1f7c896/charset_normalizer-3.5.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7ac76cf9afd34929d76eb7fcb63be476a4853d8a96f0dcf2d0db68a0cbdf9885", size = 227861, upload-time = "2026-08-15T08:18:39.315Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a3/887c1642f0da26000b0e0652d91071113c0e72cea33952e225cf589f49a9/charset_normalizer-3.5.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a3a370082ce34d0612f421e15fe011c53bb1feff21a26d06ad4fb244dab5a375", size = 260758, upload-time = "2026-08-15T08:18:40.88Z" }, + { url = "https://files.pythonhosted.org/packages/3e/11/e6f5b9a3d0e55b0ef7505cd3765cdd48f22db89994c947b316f52f801fd8/charset_normalizer-3.5.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:256dd4d85d9e4dc595e2bc983c980e73f62ddeb3165c58b4c3dfe78c5c8548c1", size = 259950, upload-time = "2026-08-15T08:18:42.351Z" }, + { url = "https://files.pythonhosted.org/packages/1b/ee/e4e10a94d51cd1ee638aa7e00b65399e6b2a4e8376ab6d2eac9f95586671/charset_normalizer-3.5.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:58d4aa13a59c969dbfdf9e6a9560e242cbfd9e8a8f50c2747714df1a423adf65", size = 249329, upload-time = "2026-08-15T08:18:43.914Z" }, + { url = "https://files.pythonhosted.org/packages/c4/25/d5f4198819e6059735a84e8d0bfb72dc33976da67b97adcd3fb5a5e07ec6/charset_normalizer-3.5.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0c6dfb5ca6723eeed15aa8e564a014d69fcb8812f94eef11fe3631e0508199f5", size = 243137, upload-time = "2026-08-15T08:18:45.368Z" }, + { url = "https://files.pythonhosted.org/packages/a5/e9/e925ca7569cf9fb9701fd82503fee73eea5268fdb856bdd64947092d3daa/charset_normalizer-3.5.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c010f5581d9c612804cc59fcf7b524b707fbcb72828551237ab545bb5c7034af", size = 242820, upload-time = "2026-08-15T08:18:46.842Z" }, + { url = "https://files.pythonhosted.org/packages/34/17/672c251a888ed2aebcdd2fe830ad0104e25ff83c43f5c4f9c15e9fc6853c/charset_normalizer-3.5.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:52ec005752a56ae79547a05c0139ca2501a0c866390b6115008456b9f0e7cde1", size = 230504, upload-time = "2026-08-15T08:18:48.353Z" }, + { url = "https://files.pythonhosted.org/packages/3f/fc/f6a85abebd42ce4da2f1db0aa56cc6a0df1995e318b3875d14401b8381d1/charset_normalizer-3.5.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2bced4061f000f7187254a02ad3433ae17eaf991747ceea2f478422590a5bba9", size = 263087, upload-time = "2026-08-15T08:18:49.859Z" }, + { url = "https://files.pythonhosted.org/packages/98/66/7c42677e739ba66746b297e2046918d793078094dc239e1e72768cffccc6/charset_normalizer-3.5.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:9eea3ab2597a5e65fe65296e2d6a84570845a6b55532d90333d740d48bbc850a", size = 243269, upload-time = "2026-08-15T08:18:51.601Z" }, + { url = "https://files.pythonhosted.org/packages/de/d8/a50b79237f417af10f8c2a501ce8d1ca87829a22e69117891ca4ba20a69e/charset_normalizer-3.5.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:496846868fea80e479324862fa877f02411f2fd0f83b79ccee2607aa68b2a032", size = 258766, upload-time = "2026-08-15T08:18:53.23Z" }, + { url = "https://files.pythonhosted.org/packages/2e/1d/0fc91aeaeb3c83b748f532399ce67cf84604b48297405d740000f7a9e786/charset_normalizer-3.5.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:85d5855daafc240cc045c026d7a15fd198a09b0fc8ff6f5ecbb5297b509cb11e", size = 250814, upload-time = "2026-08-15T08:18:54.768Z" }, + { url = "https://files.pythonhosted.org/packages/ae/10/3d8c777cf9024615295aa1b808324ad5b4a77855869c00824bad74ffaf8a/charset_normalizer-3.5.1-cp314-cp314t-win32.whl", hash = "sha256:58d3e12c88e0950bca850ae1f7c256055c097639c2edb9eb123af9807d8b15e4", size = 191074, upload-time = "2026-08-15T08:18:56.305Z" }, + { url = "https://files.pythonhosted.org/packages/4d/81/ae557d3c44d1a1d688696d60563413a0866a91b7ebc50f20df838be3d8c8/charset_normalizer-3.5.1-cp314-cp314t-win_amd64.whl", hash = "sha256:acaf604462bf330b0d07e7a07c1d6e4adac79e5fb13e9c5140590542cafacc00", size = 216476, upload-time = "2026-08-15T08:18:57.889Z" }, + { url = "https://files.pythonhosted.org/packages/27/e9/61c01fb8b804692569c036b3fc50495814502dcf13a60649c6055390b02c/charset_normalizer-3.5.1-cp314-cp314t-win_arm64.whl", hash = "sha256:fdb8a068947befafba9952162645dc2fecaeb400e64584829ed5e9b2fbe21a7f", size = 194115, upload-time = "2026-08-15T08:18:59.418Z" }, + { url = "https://files.pythonhosted.org/packages/4a/4e/8544831ef59d8f27ce92c80871380fdacc8076a8a56ed62f82e54f991333/charset_normalizer-3.5.1-cp315-cp315-macosx_10_15_universal2.whl", hash = "sha256:9085f87b0e38a2b92b8923059b4e8789fe40d9279712d15dcc670048d77079af", size = 342048, upload-time = "2026-08-15T08:19:01.054Z" }, + { url = "https://files.pythonhosted.org/packages/7f/a6/e3b46852424246065355644f4fb6dbccc0239a42a2eee27ecfc8957f0bcd/charset_normalizer-3.5.1-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2679de311c7946dde5d3b6f44941844133ff5c7cb86099c0061ab1e8901c20a8", size = 242997, upload-time = "2026-08-15T08:19:02.492Z" }, + { url = "https://files.pythonhosted.org/packages/03/3b/0cc9a26777334ab2f2e3089b948bbf4e4fe72ea70b897715ef6415043ec8/charset_normalizer-3.5.1-cp315-cp315-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:baf3775a2635e5a11fbd5e4e64ee69c7e86875d224a5c72aca4c141064589a90", size = 237014, upload-time = "2026-08-15T08:19:03.943Z" }, + { url = "https://files.pythonhosted.org/packages/8c/c2/027335f0aa337a2a2e121bac1ad88c4f02ba6053ea0926802784f3db11af/charset_normalizer-3.5.1-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ac8c94b6539074e0f40899301273ac8402b9b3e01c7b7ba269ff30340aaaf20", size = 266174, upload-time = "2026-08-15T08:19:05.598Z" }, + { url = "https://files.pythonhosted.org/packages/86/d3/e367787febe4e74769dec0f406f2c3c8d1b955fce5aee1fd0f94e8367a45/charset_normalizer-3.5.1-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8fe532b3c966d1fb794e0698e4589d0444017ae77fc0b31edea13c0e35bcc449", size = 263361, upload-time = "2026-08-15T08:19:07.251Z" }, + { url = "https://files.pythonhosted.org/packages/af/3d/391b193eb9f3e84b02f9314088c386debdc0debee843535aaea2e2c6715d/charset_normalizer-3.5.1-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5c84bec0ab5ae0c64bfe73a7d2adcb5ce73b467523fc27fd6a28ab2aa6cbe35a", size = 252143, upload-time = "2026-08-15T08:19:08.816Z" }, + { url = "https://files.pythonhosted.org/packages/2e/57/de221f1745a90d418199761967e2776bfe2c275a1194220985e8c1d37833/charset_normalizer-3.5.1-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:854066be00447fa8de2ccbbe893e2ffc4b123ef16d897af794c1e18bd4a714b0", size = 252086, upload-time = "2026-08-15T08:19:10.255Z" }, + { url = "https://files.pythonhosted.org/packages/c8/e3/d119f86a01f9331e8186175f24873b1d74a7ee9e2e4b4d68f9947dae5afd/charset_normalizer-3.5.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:21b82d8082f6f5e7f456ef0bd16323d08de1266efbfeb476e64b2a91d1471a4e", size = 245231, upload-time = "2026-08-15T08:19:11.807Z" }, + { url = "https://files.pythonhosted.org/packages/26/de/d8e48c135ae480879539cdb179c8d3b50c7879497d75dd899b5763b69cee/charset_normalizer-3.5.1-cp315-cp315-musllinux_1_2_armv7l.whl", hash = "sha256:838648accb3a7fd9803fd45c87bce8509648eb0c11bc34e216141300977244f2", size = 241546, upload-time = "2026-08-15T08:19:13.416Z" }, + { url = "https://files.pythonhosted.org/packages/67/c4/217755fd1abc50d326c252922cd642002758095a81ff45010337b8b3ef65/charset_normalizer-3.5.1-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:195ce897c6153c0700078142cf8efe3e6454ca4cf4357499e4078dfd83396626", size = 267033, upload-time = "2026-08-15T08:19:14.981Z" }, + { url = "https://files.pythonhosted.org/packages/b8/d7/34d8e404e358d2adcc5a228c2134643af00104c8fb0bf525f3688d756f05/charset_normalizer-3.5.1-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:978eab16f55b4ab2c2a745be9a0a840bf8f09a7f227d9c76eb30214d078865a5", size = 252045, upload-time = "2026-08-15T08:19:16.618Z" }, + { url = "https://files.pythonhosted.org/packages/5e/fa/40414471acf0aa0692ca77305aa00e434fcd8288f0941c93c30e9a5f8f2f/charset_normalizer-3.5.1-cp315-cp315-musllinux_1_2_s390x.whl", hash = "sha256:cc0329df4caaceb950d2f580b5ac716a377f7059624a0bafaeaf8a218c6ed774", size = 264866, upload-time = "2026-08-15T08:19:18.101Z" }, + { url = "https://files.pythonhosted.org/packages/32/90/fcc850bae791abd2e0c041847f13e270aa08692a79f3e00de6d2dce1cb50/charset_normalizer-3.5.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:687c9ca3035544b113bea2055e180af96fb63c0c476e22a9180f51925186e7b7", size = 253932, upload-time = "2026-08-15T08:19:19.734Z" }, + { url = "https://files.pythonhosted.org/packages/af/af/53afe99068b3c10b4cbae592a52ef72a7c92c0188440e83ee3a078fd8f75/charset_normalizer-3.5.1-cp315-cp315-win32.whl", hash = "sha256:706bfd38730a5ac7a365793269a00f4e988178cec121391f4248d84ad8c972e9", size = 180320, upload-time = "2026-08-15T08:19:21.37Z" }, + { url = "https://files.pythonhosted.org/packages/c9/bc/f46a132041b29e4a8779ed712d3df1bf112e94ca8de58b66d7ec2c0cf8b9/charset_normalizer-3.5.1-cp315-cp315-win_amd64.whl", hash = "sha256:92caef967d287a407085d61176fce4012b1dd62daed4eb6d5ceb26d3d2538712", size = 204174, upload-time = "2026-08-15T08:19:23.088Z" }, + { url = "https://files.pythonhosted.org/packages/a1/5d/9ed554480eda8e447b673648628fdc29574d23dbad01fe11837adedd1cae/charset_normalizer-3.5.1-cp315-cp315-win_arm64.whl", hash = "sha256:5fc45d653ea8c9a20479167e11d4a0f8cb2fa3470737ab6f9c827532313187b7", size = 184126, upload-time = "2026-08-15T08:19:24.471Z" }, + { url = "https://files.pythonhosted.org/packages/3b/32/9b8929bf384061ee1fe5d9c27c6f9776d3d824039ad4e14c88ec00c7808e/charset_normalizer-3.5.1-cp315-cp315t-macosx_10_15_universal2.whl", hash = "sha256:59171c6e45bf07d0d5cab3b0bf81d945035530f6873398b3b531c31184d46663", size = 381441, upload-time = "2026-08-15T08:19:26.038Z" }, + { url = "https://files.pythonhosted.org/packages/96/10/e9aa7923d3ddac652c99a1c5f7be494e737e151566a44abe018daf757f2c/charset_normalizer-3.5.1-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9dbdd9205662134957cf0c324f639bdc5031c0ca056e2369e238db75187c0f11", size = 241742, upload-time = "2026-08-15T08:19:27.532Z" }, + { url = "https://files.pythonhosted.org/packages/28/53/a2d249ebddf47b889a100c0bdcb61a2f9dbb8bc24ef325cc062e4f476877/charset_normalizer-3.5.1-cp315-cp315t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e4b018dc5a0eee4676e38fe84a47a427816c590b93b55d9025274ec4d6ffc2dc", size = 235298, upload-time = "2026-08-15T08:19:29.274Z" }, + { url = "https://files.pythonhosted.org/packages/7d/07/469f78af590f7d5cd48e20d8dbfa3d66deeff9ba37768c04d886b5afd45c/charset_normalizer-3.5.1-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ced3fdd71aaa83ce593746c2edb42b7a59cb4c19c8b5c407781c72e493aae55a", size = 262500, upload-time = "2026-08-15T08:19:30.955Z" }, + { url = "https://files.pythonhosted.org/packages/55/66/3bb56a47f7dcba014055b1a1d33c6f08bbe9c1e74dba154cfa25f90ae885/charset_normalizer-3.5.1-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:19a3dd5aa73cef1c99687c4fc57db016a9c17104ae1185da88ba566a5d3bebe4", size = 258888, upload-time = "2026-08-15T08:19:32.458Z" }, + { url = "https://files.pythonhosted.org/packages/ff/c1/2adc2800903fb013210349313b710a5376856578d9e33e6b9a1d8b36714a/charset_normalizer-3.5.1-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cc5d36d96478aa9c60654bd932525bf32964c62a7281eafdf16d85003a8d6004", size = 250243, upload-time = "2026-08-15T08:19:33.94Z" }, + { url = "https://files.pythonhosted.org/packages/95/b5/a18d0dd1157ab655cc2cb14a545f4a4784bbad70ab3502412e36097502d9/charset_normalizer-3.5.1-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:04368edf83514385ffc3e1cfd4546e595f4f1272dd23ba437a93a9cc3741d47b", size = 249871, upload-time = "2026-08-15T08:19:35.413Z" }, + { url = "https://files.pythonhosted.org/packages/ad/c3/525f508cd1e58d0450ac55ed40ac75bc3a97482c59def5278456a5fbf03c/charset_normalizer-3.5.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:9b5db6052055d34d41230fb78d7c439c23dc536a9896f6cb039e8dd92cfc1263", size = 243580, upload-time = "2026-08-15T08:19:36.886Z" }, + { url = "https://files.pythonhosted.org/packages/7c/c1/49a91fe7e97c8140094ca5c64161ab623a70d9f636bf834eace14048acb5/charset_normalizer-3.5.1-cp315-cp315t-musllinux_1_2_armv7l.whl", hash = "sha256:252d099029bcbea642f2a06c4ed5046bdf8b5a8150b64afa5e027e88b106e5ee", size = 239807, upload-time = "2026-08-15T08:19:38.392Z" }, + { url = "https://files.pythonhosted.org/packages/d3/58/56a48c296601274c4689b864a8e2dfb209b81dfcb39472753ce95eea662b/charset_normalizer-3.5.1-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:6199d5606e2bbf2b096cf64d03f8b6790c91081d5ac866b8e7bb6422738cc60c", size = 264083, upload-time = "2026-08-15T08:19:39.856Z" }, + { url = "https://files.pythonhosted.org/packages/10/4c/dc48409274a1817ff349711d26c62aa0c597df865d4d69ef79160c859193/charset_normalizer-3.5.1-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:77efcff2b23071c349402ac1066667a3d011f62398d81408c9b88ad991747c9e", size = 250317, upload-time = "2026-08-15T08:19:41.53Z" }, + { url = "https://files.pythonhosted.org/packages/81/58/d325912115caec62d6bdd77bbab5e0b7da5d234a9f20affdffcbcb530d0b/charset_normalizer-3.5.1-cp315-cp315t-musllinux_1_2_s390x.whl", hash = "sha256:a5cbd90ecf0fc62e64726917ad083b73001f0563657a87ec3c0b504e277dc90d", size = 258173, upload-time = "2026-08-15T08:19:43.07Z" }, + { url = "https://files.pythonhosted.org/packages/34/f7/b13b1ccae2c8ec63980d13be1890eb73f8aeabbfce02a24aabc0908788f5/charset_normalizer-3.5.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:4d26f14f041e83dd8edfd61f4cd4fa7285d31798b5bf1f28e70c367ba6c41d61", size = 251960, upload-time = "2026-08-15T08:19:44.587Z" }, + { url = "https://files.pythonhosted.org/packages/1e/25/ed3f9919c5aef8cc818be1f972f565f7610d7b2076b8ebb98839516ffc3c/charset_normalizer-3.5.1-cp315-cp315t-win32.whl", hash = "sha256:ac13b004224fb341e1e25a1ed5e19d32f57cdb2a403e01f003b46f051a550f6f", size = 191186, upload-time = "2026-08-15T08:19:46.293Z" }, + { url = "https://files.pythonhosted.org/packages/69/d5/43c2b3e9d8267092b913eb8b0603f0f71993c395632886bd37a7223f96cf/charset_normalizer-3.5.1-cp315-cp315t-win_amd64.whl", hash = "sha256:35aea775dc2bd5f54cd84a1cd2696cc3207c479cb9cf0bd346f0d343e4300ddb", size = 215947, upload-time = "2026-08-15T08:19:47.853Z" }, + { url = "https://files.pythonhosted.org/packages/a8/76/9aad3e9c8865e5e0efa9a7f6f81c37a67635a985145ecd44528a81e088ee/charset_normalizer-3.5.1-cp315-cp315t-win_arm64.whl", hash = "sha256:fb78f6e7fcd8ad785d28cd577168bc1aaee827b25bb8755638f694794ea98f0a", size = 193909, upload-time = "2026-08-15T08:19:49.383Z" }, + { url = "https://files.pythonhosted.org/packages/5b/97/fb4e82231aba271ffd775a1b4993b0defc4e3059f286ae41d9433409fe85/charset_normalizer-3.5.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:41876ee62a3dddf48ff1121ad8f0798032aa03f2fd35f21f34a4cab14f18d8d2", size = 331467, upload-time = "2026-08-15T08:19:50.959Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2f/fe3f187327aac18e2d54e9d2b08e15d27bf9b642d9e51c219f130fc34d1a/charset_normalizer-3.5.1-cp37-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a6dac12ff6b846103483683f60c5f8fee205121adc58ffd87e90a90a3af69e99", size = 253057, upload-time = "2026-08-15T08:19:52.654Z" }, + { url = "https://files.pythonhosted.org/packages/d7/c7/9e48cee5c161fe24da823b61bf381921d77cb994a0a4de148e95018c1984/charset_normalizer-3.5.1-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cee5dd7c6fb5dd52a0fe2a740f9bc6e3593f5f8b1788bde49de02086f30182b2", size = 240930, upload-time = "2026-08-15T08:19:54.163Z" }, + { url = "https://files.pythonhosted.org/packages/49/e0/716601f3cc69be7b198951150c75ead1ece33c3c8036ff6ffa46029659a0/charset_normalizer-3.5.1-cp37-abi3-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:343fb4f2821043bd87095f7b08a1a181febc8e36ac64212143bbfd0a0e1bc235", size = 230822, upload-time = "2026-08-15T08:19:55.807Z" }, + { url = "https://files.pythonhosted.org/packages/d3/05/71bfc5caa0abcc45aea1f6a4d50ac68e59605ddc7666fe8494f4cd229665/charset_normalizer-3.5.1-cp37-abi3-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ae4a097991662cd4fff0ddc74e0fe7874f82e00042fa0ea00855645ed0c79598", size = 260037, upload-time = "2026-08-15T08:19:57.312Z" }, + { url = "https://files.pythonhosted.org/packages/c3/92/de7e32ed05341e7a9c4c877c318418197b7f2d66a3b68d561bf2ac57ca3e/charset_normalizer-3.5.1-cp37-abi3-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4b599739b93b2cbeded49645ae3c8d1405c29ddfbceac1545c87a3f9580a9e96", size = 255097, upload-time = "2026-08-15T08:19:59.056Z" }, + { url = "https://files.pythonhosted.org/packages/f5/7b/ade0a122600319dfa0b1000ab0f9731c94a817904cf3c5de408c73a4ede7/charset_normalizer-3.5.1-cp37-abi3-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b39b69b347e5e47a3b5b8cfc005c68c1ba347474e3960236c4944a8ecd174962", size = 250166, upload-time = "2026-08-15T08:20:00.612Z" }, + { url = "https://files.pythonhosted.org/packages/75/9c/019fbb9f4834491a160951349b1a3714439376f66e5f7cf18b4f18f0c7aa/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:a2028475ba855475b8b4d3cfeb4994269c967aea8b9892dfba907f4263a863a3", size = 241821, upload-time = "2026-08-15T08:20:02.321Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b8/11d4840bfc99330cc7fbcc2681ee5a044553a6e77655508d8f9b2bff7b34/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:36047af20e17097c3bb9476c2b7655f2f7aa51322c0ba58c07695bedf755a950", size = 232529, upload-time = "2026-08-15T08:20:04.008Z" }, + { url = "https://files.pythonhosted.org/packages/18/96/2b3a21492d9f65171ac75d872f5018260013d00bfa0ff70ec9f179148cbd/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:4c4fb141a727957c93edfe5c32a26ceb6b5f6461d67146e2d39f51e16170bea8", size = 260348, upload-time = "2026-08-15T08:20:05.877Z" }, + { url = "https://files.pythonhosted.org/packages/d6/aa/a69a2028e8bd052476c245460ab19d7de595de084dd968f2d75cd50c3e25/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:2f293479cce755c75f1697e87c409b7ae4c555c7dfecb6e988ad13abba943031", size = 247234, upload-time = "2026-08-15T08:20:07.487Z" }, + { url = "https://files.pythonhosted.org/packages/35/8a/3d130aeabcaf3d2466af76b7b141c08d9e89c9016ab4b7cdd0f7dc2d1c62/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_s390x.whl", hash = "sha256:3588e376b3ea2eea84976f67273d679f229e24c66dce7b82ae45aef04ff6e072", size = 256917, upload-time = "2026-08-15T08:20:09.142Z" }, + { url = "https://files.pythonhosted.org/packages/80/c2/a7379b840292d0c1ab9fbd17d1f3967aa81794dc95bc74be8999d7fedcf7/charset_normalizer-3.5.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e199fb99720074809a7720f1c0b4d919eea8b87e88713e0f8f602f7bef543d9d", size = 254846, upload-time = "2026-08-15T08:20:10.727Z" }, + { url = "https://files.pythonhosted.org/packages/01/65/d43b714731bb2f40d4053dfa00ecfc1c5a301f8e3316c5db3a09af59fe94/charset_normalizer-3.5.1-cp37-abi3-win32.whl", hash = "sha256:dd732602a7009217f658d5863d12d79d373a4de0eebc111094bcdd3bb8e0a6cc", size = 174216, upload-time = "2026-08-15T08:20:12.334Z" }, + { url = "https://files.pythonhosted.org/packages/35/4f/b911ed898b26a09789eba9c9200c999aff6c61b4bafaf4838e56d1a1e1a3/charset_normalizer-3.5.1-cp37-abi3-win_amd64.whl", hash = "sha256:70055ff39b97c99e7ae40ea3e393fb62aa2e44dbd9b29f8d14f42fb0025c3959", size = 199764, upload-time = "2026-08-15T08:20:13.908Z" }, + { url = "https://files.pythonhosted.org/packages/f0/a7/920baf467bfd9bf689f3b318340f37aee4572a71f162bd8db51da55ba4fa/charset_normalizer-3.5.1-cp37-abi3-win_arm64.whl", hash = "sha256:87e4f41d375c0b9be2fb5251aee4b8a689169e134535aed81bf085c3b647451e", size = 287318, upload-time = "2026-08-15T08:20:15.551Z" }, + { url = "https://files.pythonhosted.org/packages/cc/61/d01fc49b8dea277640b55a9e15960dbca9fdc8c9fde18e572d39c59f4019/charset_normalizer-3.5.1-py3-none-any.whl", hash = "sha256:6df0ec430f9a831772c23ca5a224cba36517a58a84bb32c32bb59a9fa67c47f6", size = 68658, upload-time = "2026-08-15T08:20:43.306Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "distro" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, +] + +[[package]] +name = "django" +version = "5.2.17" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asgiref" }, + { name = "sqlparse" }, + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d5/d8/43e9d000519adceb189620b6869ff88031e046df91c2e9da72f8f6918399/django-5.2.17.tar.gz", hash = "sha256:9d4d93be539a18ab80d058eb515900e10951e04c537c5a6b394fc49528d3251f", size = 10889740, upload-time = "2026-08-04T15:04:03.173Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/f8/ce120525ca78f12b07daf65786679c5d0b54a75285a8958d3ae55e39da35/django-5.2.17-py3-none-any.whl", hash = "sha256:f04fb3b36ee119e1af4fa1d397d5fd6cf12700f49321e84d4f4c642c5b1973db", size = 8315563, upload-time = "2026-08-04T15:03:59.1Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[[package]] +name = "idna" +version = "3.18" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/63/9496c57188a2ee585e0f1db071d75089a11e98aa86eb99d9d7618fc1edce/idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848", size = 196711, upload-time = "2026-06-02T14:34:07.794Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", size = 65455, upload-time = "2026-06-02T14:34:06.319Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "jsonpatch" +version = "1.33" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonpointer" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/78/18813351fe5d63acad16aec57f94ec2b70a09e53ca98145589e185423873/jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c", size = 21699, upload-time = "2023-06-26T12:07:29.144Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/73/07/02e16ed01e04a374e644b575638ec7987ae846d25ad97bcc9945a3ee4b0e/jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade", size = 12898, upload-time = "2023-06-16T21:01:28.466Z" }, +] + +[[package]] +name = "jsonpointer" +version = "3.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/c7/af399a2e7a67fd18d63c40c5e62d3af4e67b836a2107468b6a5ea24c4304/jsonpointer-3.1.1.tar.gz", hash = "sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900", size = 9068, upload-time = "2026-03-23T22:32:32.458Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl", hash = "sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca", size = 7659, upload-time = "2026-03-23T22:32:31.568Z" }, +] + +[[package]] +name = "langchain-core" +version = "0.3.86" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonpatch" }, + { name = "langsmith" }, + { name = "packaging" }, + { name = "pydantic" }, + { name = "pyyaml" }, + { name = "tenacity" }, + { name = "typing-extensions" }, + { name = "uuid-utils" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fe/8d/d54586b8f65c6fc209db93916ff9e919e1cc14bad8fe66880ea4d7ea9d6c/langchain_core-0.3.86.tar.gz", hash = "sha256:671cbc96a325fe47f7dbab421236ada2d437bc4bfad0038102264885d0b462e2", size = 603154, upload-time = "2026-05-07T16:48:08.14Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/93/ba19ca54701c6118e68f8785949b6c0eab1df3a5cfa5310508cc86877994/langchain_core-0.3.86-py3-none-any.whl", hash = "sha256:7d2a1c50d2d2a139dbc6465cd339f32d14aa43db5ac9bd232e5b567a238709e8", size = 461306, upload-time = "2026-05-07T16:48:06.283Z" }, +] + +[[package]] +name = "langgraph" +version = "0.2.76" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "langchain-core" }, + { name = "langgraph-checkpoint" }, + { name = "langgraph-sdk" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ee/62/8d484e498ec95d5a8c71e78f5a2d09ff280db0c99737b7aef0524cd67076/langgraph-0.2.76.tar.gz", hash = "sha256:688f8dcd9b6797ba78384599e0de944773000c75156ad1e186490e99e89fa5c0", size = 133005, upload-time = "2025-02-26T21:57:39.108Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/52/a9a84d94353ebcc565b2246849d59d71023b4c33109f46e1ef799ab40bd1/langgraph-0.2.76-py3-none-any.whl", hash = "sha256:076b8b5d2fc5a9761c46a7618430cfa5c978a8012257c43cbc127b27e0fd7872", size = 153684, upload-time = "2025-02-26T21:57:37.223Z" }, +] + +[[package]] +name = "langgraph-checkpoint" +version = "2.1.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "langchain-core" }, + { name = "ormsgpack" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/29/83/6404f6ed23a91d7bc63d7df902d144548434237d017820ceaa8d014035f2/langgraph_checkpoint-2.1.2.tar.gz", hash = "sha256:112e9d067a6eff8937caf198421b1ffba8d9207193f14ac6f89930c1260c06f9", size = 142420, upload-time = "2025-10-07T17:45:17.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c4/f2/06bf5addf8ee664291e1b9ffa1f28fc9d97e59806dc7de5aea9844cbf335/langgraph_checkpoint-2.1.2-py3-none-any.whl", hash = "sha256:911ebffb069fd01775d4b5184c04aaafc2962fcdf50cf49d524cd4367c4d0c60", size = 45763, upload-time = "2025-10-07T17:45:16.19Z" }, +] + +[[package]] +name = "langgraph-sdk" +version = "0.1.74" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, + { name = "orjson" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/f7/3807b72988f7eef5e0eb41e7e695eca50f3ed31f7cab5602db3b651c85ff/langgraph_sdk-0.1.74.tar.gz", hash = "sha256:7450e0db5b226cc2e5328ca22c5968725873630ef47c4206a30707cb25dc3ad6", size = 72190, upload-time = "2025-07-21T16:36:50.032Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/1a/3eacc4df8127781ee4b0b1e5cad7dbaf12510f58c42cbcb9d1e2dba2a164/langgraph_sdk-0.1.74-py3-none-any.whl", hash = "sha256:3a265c3757fe0048adad4391d10486db63ef7aa5a2cbd22da22d4503554cb890", size = 50254, upload-time = "2025-07-21T16:36:49.134Z" }, +] + +[[package]] +name = "langsmith" +version = "0.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "httpx" }, + { name = "orjson", marker = "platform_python_implementation != 'PyPy'" }, + { name = "packaging" }, + { name = "pydantic" }, + { name = "requests" }, + { name = "requests-toolbelt" }, + { name = "sniffio" }, + { name = "typing-extensions" }, + { name = "uuid-utils" }, + { name = "websockets" }, + { name = "xxhash" }, + { name = "zstandard" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/62/a917e87073767db8ca335c3f5a42fb4c5336509b8d5b03e165e46da47e70/langsmith-0.11.0.tar.gz", hash = "sha256:7339f90e6fd9a1a009445b5084a7a0e56a8b6f17305ee5d7e8c5e7582217854f", size = 4805612, upload-time = "2026-08-14T12:56:55.409Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/aa/18d334f04c12bb9154568747539a1143a93d0c34b894662c065454f396c8/langsmith-0.11.0-py3-none-any.whl", hash = "sha256:e87a3929915936c066b3fa3283ec3f3f0013e2ef7f98a443a7fbe3fab8e784a3", size = 737950, upload-time = "2026-08-14T12:56:53.014Z" }, +] + +[[package]] +name = "llvmlite" +version = "0.49.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/27/72ae94ea5c8f7349ec1c229d4cd058feb799cbd0833ad6d1b47c919b37b7/llvmlite-0.49.0.tar.gz", hash = "sha256:00f16db782f4a13c78c5804aedc434e46794a77e89999a168f9401106270e50a", size = 194467, upload-time = "2026-08-11T16:26:00.489Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6b/ae/3f699ebe3590e15e023a6372dd147526fd8ec398aacf9ceb844e854964a8/llvmlite-0.49.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:b541c8fac3450db7574d1f53cf9dff83f285bfed9d69bf81fe71fc2a7d4f97fe", size = 40479231, upload-time = "2026-08-11T16:23:56.773Z" }, + { url = "https://files.pythonhosted.org/packages/be/3c/e97f69c62a2d972066d9a2612ce1f3de313035ac897a5b9f787cad8b55f7/llvmlite-0.49.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6acba646d88abbc87d5c113a3d62c1fbf8b8fee11c6493f516803e30f21ae870", size = 59890658, upload-time = "2026-08-11T16:24:05.451Z" }, + { url = "https://files.pythonhosted.org/packages/69/e6/e942ee08605fc0526ff3854260c384d8315a5830e16c4c2a5aebc14dc9bf/llvmlite-0.49.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4ec8ad805e7515cb8440a690eb3cef4d34acb29eef80b705ec4e1c1ad3c43c68", size = 58344481, upload-time = "2026-08-11T16:24:13.503Z" }, + { url = "https://files.pythonhosted.org/packages/84/49/2a44871cac6b5a2fd4aabd68cfdaf6de9a5c7edb36dee5d47b77bda4b50f/llvmlite-0.49.0-cp312-cp312-win_amd64.whl", hash = "sha256:3a9c9e3af4e214acfefa4f73ebe7bc3fb35854a62b654edb3953f5ae33c08ba3", size = 41865543, upload-time = "2026-08-11T16:24:20.41Z" }, + { url = "https://files.pythonhosted.org/packages/7d/85/0b536a3c59f2636d9dd51dda832b6c1d0ffec37608429dedf128664918f1/llvmlite-0.49.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:039fa4054a06f537fb39248d4472284ca96be311a142ec09e69f95630ab469cc", size = 40479230, upload-time = "2026-08-11T16:24:27.295Z" }, + { url = "https://files.pythonhosted.org/packages/8e/1c/ca8ba47b057b793099784475499771780ec46839f2782f753a7079d23520/llvmlite-0.49.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ddc7aecd4f56397ed6e8f120ec5dcd5a1a8f0e6032ca4af413462792d4dca2e3", size = 59890659, upload-time = "2026-08-11T16:24:35.595Z" }, + { url = "https://files.pythonhosted.org/packages/de/af/9526dfdd33a923f33e29a18b8f9801ee7ee4b7397e88d28192c1024c4a75/llvmlite-0.49.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d3dee64784201b64c13a8df62c48a4f4218858faaa65889866bb29bdc243c038", size = 58344482, upload-time = "2026-08-11T16:24:45.79Z" }, + { url = "https://files.pythonhosted.org/packages/96/7f/9f5afcf6476b228d6b170408f377a0c4f91477fc1fc91f8141088b45bf46/llvmlite-0.49.0-cp313-cp313-win_amd64.whl", hash = "sha256:a1b414dc6b164738ec39dd8987cea73829057b7dd92fc6d91b52838385fc1dd2", size = 41865544, upload-time = "2026-08-11T16:24:53.962Z" }, + { url = "https://files.pythonhosted.org/packages/25/d1/16599b8c9f21802448059482eab48a9e74086dc56b901a677ba355565e64/llvmlite-0.49.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:80a84683d04516bb51da1bbeebddaf2c2f558809c93078a8f91807909ae331f8", size = 40479230, upload-time = "2026-08-11T16:25:01.513Z" }, + { url = "https://files.pythonhosted.org/packages/3a/61/0b23849141a4c4e7091fcd158ebb45195896974bebca3e58fee7cad4b4f4/llvmlite-0.49.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4281a0171d66d2098adce4ba706b8c550b1b10718650f682d64cde16e84e4de5", size = 59890659, upload-time = "2026-08-11T16:25:08.733Z" }, + { url = "https://files.pythonhosted.org/packages/c4/92/628692b74b31e27af9ba7e8ba651941ee4956959d5478123c453f59aad4a/llvmlite-0.49.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b095f15fb12c4d90495df5b1a3772b4732cc408398b204a787dbedd370e09c69", size = 58344479, upload-time = "2026-08-11T16:25:15.731Z" }, + { url = "https://files.pythonhosted.org/packages/96/8a/412fc273521b02cbfe0b5f8ad56cc696385f6eaeecdb9e9ae6a90111d98d/llvmlite-0.49.0-cp314-cp314-win_amd64.whl", hash = "sha256:294e2f0b70aef8f92d0ae7b203e2609f08beb39437eee73de59a21669331aae9", size = 42986588, upload-time = "2026-08-11T16:25:22.534Z" }, + { url = "https://files.pythonhosted.org/packages/fc/15/f47cf45c00c8b165ac3d268502dcb21d900e86f27fd338268a66ce922ab0/llvmlite-0.49.0-cp314-cp314-win_arm64.whl", hash = "sha256:95d1071023ed858b79f6971954fd7cc1f5dbcbab987718a4ccbe1411e47d0b81", size = 37441881, upload-time = "2026-08-11T16:25:28.324Z" }, + { url = "https://files.pythonhosted.org/packages/e8/2e/eafd488766d1c02413cba24f7b22acb9b3ccdfd8407e98d30eb16bac4e2a/llvmlite-0.49.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:f3f2ff0aeb17d34fcce9f79b99baac441cfd3efa41b83e233ca4530a72381f72", size = 40479230, upload-time = "2026-08-11T16:25:35.125Z" }, + { url = "https://files.pythonhosted.org/packages/98/07/a2c4f04e2111ccc274b4d5e3331398a9dcf6d6e5e55d6444b1ad9d6381cf/llvmlite-0.49.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d5555ea1d63928481cbf7fcb1d67452b216c7e5b393a4eb7aa1401e67f2a4fc4", size = 59890658, upload-time = "2026-08-11T16:25:43.294Z" }, + { url = "https://files.pythonhosted.org/packages/80/f9/7b7b50f80b4585bcd78675ff3110c256877b11df32a8cde284f851762f57/llvmlite-0.49.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32adb84fdaae28aeb86fdb6253084ee707ee157289a2e98fe3caf48a62bee82", size = 58344482, upload-time = "2026-08-11T16:25:51.527Z" }, + { url = "https://files.pythonhosted.org/packages/d8/c6/32d68bfbf1d0c36888530ef6fd72864861af23dc546302b41033471a8c3a/llvmlite-0.49.0-cp314-cp314t-win_amd64.whl", hash = "sha256:be637e465010bc9c50f070468f7f1cf5385e92fee364d192dd5e6cea790ecba9", size = 42986602, upload-time = "2026-08-11T16:25:57.69Z" }, +] + +[[package]] +name = "numba" +version = "0.67.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "llvmlite" }, + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7a/90/2544f4e3a61e501d6c9a5418fd4b905323222693d54a02cab0106a0af865/numba-0.67.0.tar.gz", hash = "sha256:cd75aa535b33fa05d9d930b1ae8af9f97a2881e96d72dfb38ec9b78284d9f851", size = 2836515, upload-time = "2026-08-11T23:04:00.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/58/915cddba90010348ed0444451132fdde9b000bcbaff1582029b5bf115d11/numba-0.67.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:6004d8d5f28d4028687fb2d972d629295b13685943bd2ed5cd8810c3b848e219", size = 2745050, upload-time = "2026-08-11T23:03:25.607Z" }, + { url = "https://files.pythonhosted.org/packages/bb/38/926757caaac18a66f057d7544a63620bf360a07d281c9f7ecadd2aa83963/numba-0.67.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f63d43db06b4756424d6d2484737c902e0ae944a0eec3e8b0b4de2c695b15caa", size = 3884596, upload-time = "2026-08-11T23:03:27.688Z" }, + { url = "https://files.pythonhosted.org/packages/4d/6d/58291dc58da39d98b32db7f044729f6d8d4920cd9622fbab3179b54ff4c4/numba-0.67.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:76d3335aaeffb9dc88309420890e73497a00be08a7530441bc2b58ffe025bfa5", size = 3585290, upload-time = "2026-08-11T23:03:29.684Z" }, + { url = "https://files.pythonhosted.org/packages/6e/63/ab21828b4056afed71f9ecb40f4de26c2c19de731cc001961aca74b79464/numba-0.67.0-cp312-cp312-win_amd64.whl", hash = "sha256:50e2b72406c18cda5dd7431b0082cb85ea94e06c64c33607248fc8bef92cfb81", size = 2815645, upload-time = "2026-08-11T23:03:31.732Z" }, + { url = "https://files.pythonhosted.org/packages/49/dd/bd9fe772f6c84597b76cac229b3f2890f01a2c64fd70e48ceaae10dd65cb/numba-0.67.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:77e1c7173fee57a0d84e006c7e70346689d6cb3e7db503489bae58646b4eff7b", size = 2744872, upload-time = "2026-08-11T23:03:33.649Z" }, + { url = "https://files.pythonhosted.org/packages/a1/1c/c05609739cc41116d36e30cb2b41fb00f126bb52e1b0bac907051ad8a35d/numba-0.67.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9c4953387c77864b596d8296e2cfbdef82b0eea4166ab4864b05d226c51143e0", size = 3892004, upload-time = "2026-08-11T23:03:35.797Z" }, + { url = "https://files.pythonhosted.org/packages/4a/77/a5276ad4178250403e0e2251f3e1f8ac18feac779b0474a8bcb08558490d/numba-0.67.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:88f6e0f5cb6c545e158b6ef0496c01b6d6958a7ccc6634a1576a94bbbab29ff2", size = 3591878, upload-time = "2026-08-11T23:03:37.845Z" }, + { url = "https://files.pythonhosted.org/packages/0f/80/d48f0ba7442516ceb5a1585f0c81d3aa531bc96bfcabcd9f8f925768c426/numba-0.67.0-cp313-cp313-win_amd64.whl", hash = "sha256:b68ad5125fe245339cc8dcc036081fc1ea482c5063387b9612a76ccd83dc91cd", size = 2815504, upload-time = "2026-08-11T23:03:39.736Z" }, + { url = "https://files.pythonhosted.org/packages/d7/16/345b1e4774a08247aafcfdb93d4e8d24a3646366cbe72de33053fc0de1b5/numba-0.67.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:f99f880ff25f418a67f9a1d00d0ddfbc63430f627b523e515085a592a7567f4b", size = 2745088, upload-time = "2026-08-11T23:03:41.864Z" }, + { url = "https://files.pythonhosted.org/packages/1b/36/e614ba2bc0f005ed0f37a6413f08fe705210297ddb9a37a475a8b9fdab61/numba-0.67.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5269245a675abdd3e2c35ec6bb2f250355effa9032514d8f2354f0d2d10854bd", size = 3861040, upload-time = "2026-08-11T23:03:43.842Z" }, + { url = "https://files.pythonhosted.org/packages/40/90/30c42a1dbc4176cf355e8e8be61803732c55597b1332925fe233912a43d9/numba-0.67.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f074a8e23db78490f11a3930c940be758316c10ac5985be83d2f298dc080acf7", size = 3561811, upload-time = "2026-08-11T23:03:46.037Z" }, + { url = "https://files.pythonhosted.org/packages/18/6d/21bd16f770476e394c5e5f504935817967442a71251d6b86c244a2767980/numba-0.67.0-cp314-cp314-win_amd64.whl", hash = "sha256:4d576e62bf2c9370f61312b51573c4bb1f3fe96798bbab56730847a368a316c4", size = 2817421, upload-time = "2026-08-11T23:03:47.922Z" }, + { url = "https://files.pythonhosted.org/packages/95/06/bb41b0e59b9ff52c94a2f01db24f6437df058caebb377b5f372fc343a6a2/numba-0.67.0-cp314-cp314-win_arm64.whl", hash = "sha256:7930748ce8355d2a5a28602abab056a61fdc676d17377f27d17993905428171f", size = 2788885, upload-time = "2026-08-11T23:03:49.967Z" }, + { url = "https://files.pythonhosted.org/packages/10/7c/aa07151fbd0f4283f78de437cc196f9084789be89a2b4de3fdc2f6a4b414/numba-0.67.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:4a2ed006635bbd0fe45681ed49f3b4f4bad1abf0c233bcc5842c9e3a34cabd61", size = 2748150, upload-time = "2026-08-11T23:03:51.755Z" }, + { url = "https://files.pythonhosted.org/packages/74/62/b8174ca95a4cc1a7ba1520767734e016991545590b8fbde521b681701a9f/numba-0.67.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aa5f002f665bec321b950dacaa26ee009e1d720f6ac9d9856eed5efe1caa03a6", size = 3896986, upload-time = "2026-08-11T23:03:53.752Z" }, + { url = "https://files.pythonhosted.org/packages/8c/f9/3a7b6dbf81e01a48958b45ad2239edbc64707522ab17f11f9f18c44bf6d1/numba-0.67.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:83ab968b0e0fa744eba03351282dd8000796e6ec8e4518f47bd3ed86c0a20c7b", size = 3614644, upload-time = "2026-08-11T23:03:55.794Z" }, + { url = "https://files.pythonhosted.org/packages/d9/5b/248f5681c121ca853a9f4e39d342a3e01b8a0261b0275853eb3d0d56aa20/numba-0.67.0-cp314-cp314t-win_amd64.whl", hash = "sha256:00c964a5b94d3ae82d83ac162cd610755875b98dadb779fdde06e6bfcdbca47e", size = 2822870, upload-time = "2026-08-11T23:03:58.097Z" }, +] + +[[package]] +name = "numpy" +version = "2.5.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/80/db0b4559e57ec36362bedbb05530a87fafbcb6067708c946967a41d449e7/numpy-2.5.2.tar.gz", hash = "sha256:d482d171c406ae88c5b19cad3b6a1c4c5209f886ab74bc44c2c865c23f52d860", size = 20773161, upload-time = "2026-08-09T13:48:27.962Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/72/dccb0aaf40972777283303919f613964227266d0c13adebb79ac124f1c3e/numpy-2.5.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:14e373cfc6387177e8409dac3c7159be8eb05cd77096cd7c950268b86f62831c", size = 16891693, upload-time = "2026-08-09T13:44:51.702Z" }, + { url = "https://files.pythonhosted.org/packages/60/2e/b5aee50a1f74ac815cf8331812cb8251e29024025de462e0c047641c614c/numpy-2.5.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4bbd96c833ecc8cc069ce518078fc8c60cb9cbfb0fea5b7a803ad65035596d03", size = 11903109, upload-time = "2026-08-09T13:44:55.501Z" }, + { url = "https://files.pythonhosted.org/packages/f3/f4/29e78102a80601cf034d4e9767022cffeca2c3b4c926e1754572ca95593d/numpy-2.5.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:6e8172ddfcf5cf74b811d372b570b83c60bd2de87a6fbfbebdadb4a9bd9c6cbb", size = 5350202, upload-time = "2026-08-09T13:44:58.401Z" }, + { url = "https://files.pythonhosted.org/packages/11/4b/dcd3b7eadaf4035d2c7a4289d232523a6964f602598ef7674e4bd7291f93/numpy-2.5.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:65f188481f1669e26f62b701e8205d19e460fa4a9b52a1414ba382330e4a3414", size = 6687736, upload-time = "2026-08-09T13:45:00.813Z" }, + { url = "https://files.pythonhosted.org/packages/e5/21/4947e0e9d6c9fc2e2ff15b8949049ee44f63adb9cacc729ab8793f97e712/numpy-2.5.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8ee9c4eeb8454b3660a8b53493563c3e121c2fc94fbd72b848ef814ed7b676a9", size = 15612696, upload-time = "2026-08-09T13:45:04.151Z" }, + { url = "https://files.pythonhosted.org/packages/3a/5f/62d28cf019460c7f1394105b4d49d9911a9c444cb77ab0bd95a204c5a6de/numpy-2.5.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3cdec01fa790a186d430433fdd4d4ffb70eed6f0eeb4bf05c8dbe2dce0a9bcb8", size = 16722264, upload-time = "2026-08-09T13:45:07.714Z" }, + { url = "https://files.pythonhosted.org/packages/14/25/3f0be4c1b9fdf5dd5e708a6806978564d7c46a055c000496309ff2a2f8af/numpy-2.5.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7999d4ddb0c4025018373fd787510d46e04c769467af22869707b3c1cfd459ab", size = 16974396, upload-time = "2026-08-09T13:45:11.316Z" }, + { url = "https://files.pythonhosted.org/packages/22/72/6262cbdeeb45da9d971e40715f579d791603ba8ec0b5e2db1ac55454421d/numpy-2.5.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c1f017dc0875c9209d219f97feceb7d54c2661bb243deb4114478e1295808af7", size = 18476044, upload-time = "2026-08-09T13:45:14.869Z" }, + { url = "https://files.pythonhosted.org/packages/36/33/29208b8b075bde62d26a81d14b358c42b0f69b6cabd98d4ff97f37f22b05/numpy-2.5.2-cp312-cp312-win32.whl", hash = "sha256:d6a48072864e3324e194a8fbb3c657bcc5b5c869dbc64c9537b1d5c862572c0a", size = 6072817, upload-time = "2026-08-09T13:45:17.867Z" }, + { url = "https://files.pythonhosted.org/packages/7f/b9/87fea2769fe1c47c1b5b01d8310772c9d1a85d485de7cf386ef7a3332b02/numpy-2.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:28ac63476ec7651484215ee7fa15a1f78b57c14621f01e392afe17b9a1390ce4", size = 12464674, upload-time = "2026-08-09T13:45:20.734Z" }, + { url = "https://files.pythonhosted.org/packages/14/52/032b97e00461ab0809bbe4c588b035620e5a14b8cdee47ecddefc7b17d33/numpy-2.5.2-cp312-cp312-win_arm64.whl", hash = "sha256:27650bb0e7140fa3d37b9923b4803645e0b125d190f326eecfd3f4dad8e8ade1", size = 10397131, upload-time = "2026-08-09T13:45:23.73Z" }, + { url = "https://files.pythonhosted.org/packages/f5/d2/6b24738a0ef4557d189b150046cd07823c50e4273e8aebd651222e24306f/numpy-2.5.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8e4cb9a754c8a0c62eaa88273a5fba3391f4a610d1dee893c0755da31c083f15", size = 16886595, upload-time = "2026-08-09T13:45:27.323Z" }, + { url = "https://files.pythonhosted.org/packages/65/60/f2d208d366f263f39c6e69ed309290717aab41078b6d04c9be2a84fa2a07/numpy-2.5.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:52c808f96484f5571a5cc863775ce50247c17dfb3b0361f8ed6b4b0456f80080", size = 11896845, upload-time = "2026-08-09T13:45:31.638Z" }, + { url = "https://files.pythonhosted.org/packages/3c/79/81e0bf24f4d020a2b1d5cd297a9f60c3f24eeb116f9bba5870443f7b6a4a/numpy-2.5.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:29d81e97f668489cba8ebfd796b9bdd453525d35dd9e162e2daec94bf3fc7740", size = 5343880, upload-time = "2026-08-09T13:45:34.373Z" }, + { url = "https://files.pythonhosted.org/packages/ba/cc/e3141cf06d1a8a2c7e107543fe1269c1d1af760d4d683c0794a4ee1127c2/numpy-2.5.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:afb3f0632d6b2e3ba04dbce8d1e48d321b369138b73830b5ca371a0e8d479d56", size = 6682264, upload-time = "2026-08-09T13:45:36.7Z" }, + { url = "https://files.pythonhosted.org/packages/29/f1/2a64a307d92c5d98f5255a4014eb43bb6103ee477087b61ecae44a3aa9b9/numpy-2.5.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0aadf13b60048d501e05fa699efaf7734e2494f3498a4c2a5521d822640324f3", size = 15609566, upload-time = "2026-08-09T13:45:39.518Z" }, + { url = "https://files.pythonhosted.org/packages/7b/44/59a1eb68e773c4098d107ef34a0dbdeca501d72ffcfbff9a7707343921ce/numpy-2.5.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29b86ff8a6cc556b47ec6b64b194815cc80e6bf5eedcc6cddfd65318cb0b4eee", size = 16709995, upload-time = "2026-08-09T13:45:43.661Z" }, + { url = "https://files.pythonhosted.org/packages/8a/4c/3e54d4ddbc359a1295f8b633e8106bcd4d7d4a206e82df051bdfb3058755/numpy-2.5.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6950c4b7dd562453090548ba7f5da7e59f57f85663f15d5dcc60e249192f7e59", size = 16972511, upload-time = "2026-08-09T13:45:47.094Z" }, + { url = "https://files.pythonhosted.org/packages/f2/9f/02e371638ebf19b66d46231e4be52999e87f32d1961b113bc45656608b22/numpy-2.5.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9727f472d2f3888053b8a75ab0cb94745a9de224bb5846dbadc0092101bc71d", size = 18465609, upload-time = "2026-08-09T13:45:50.808Z" }, + { url = "https://files.pythonhosted.org/packages/eb/ae/ad6645abc7a3510fe48e8ea1ab4598166f500057ef4ebf38bfad4f1577de/numpy-2.5.2-cp313-cp313-win32.whl", hash = "sha256:4f9744f9fbdcea0bc552e8f19e1f141f811a3f9bc2be2cc6e86d982cab23e3f4", size = 6070204, upload-time = "2026-08-09T13:45:54.111Z" }, + { url = "https://files.pythonhosted.org/packages/15/20/f3489f86d81ea460b2bcdceaed094142ca6579f6be0ec527b781d39afe68/numpy-2.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:85aaccb24182c25df891ad0ec333585967e115269d5f1b17f2c9ae005bc96657", size = 12460532, upload-time = "2026-08-09T13:45:57.167Z" }, + { url = "https://files.pythonhosted.org/packages/d5/21/35b31dde1b283b79de828b80f876afd8c94e28fe1e9c375f89e261cc4c0d/numpy-2.5.2-cp313-cp313-win_arm64.whl", hash = "sha256:bd68ece1553d2023c09a4226d9e41c586ad2d20594d1a456186c33513d2cb3f2", size = 10396725, upload-time = "2026-08-09T13:46:00.478Z" }, + { url = "https://files.pythonhosted.org/packages/ac/f8/c3b222bf075b50afd8e949a07a15c4b312a4a84bd8102a332bcd953cbbb4/numpy-2.5.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d787cf769c3baeb5f6235e778edb52c08dfa923789b5958f28e6450f96107cb1", size = 16885180, upload-time = "2026-08-09T13:46:03.939Z" }, + { url = "https://files.pythonhosted.org/packages/17/e1/2c1d4b1987795a92b5bbf7c24fe249ab96aa2573ab0d7604802c189d7b86/numpy-2.5.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:24b9dc2e3d84aa58523798805194e23e736f3f6ce2d1a5b92583ae734e6dbda8", size = 11907878, upload-time = "2026-08-09T13:46:07.045Z" }, + { url = "https://files.pythonhosted.org/packages/b9/ee/d08226fc858044355983a6e5b94f08ff6f3969e0a2b160a4a89f0ddb3445/numpy-2.5.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:9e9413326d726c2545bfa65d2c0876871e8d8386e77f992c1d426e180bbd4323", size = 5354922, upload-time = "2026-08-09T13:46:10.04Z" }, + { url = "https://files.pythonhosted.org/packages/94/f0/6d3d933056440ebbc5e6bad92065fc6c26a48a84a36b1208580e94eea76c/numpy-2.5.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:60e902ac295855348a5ca2ea4c89108989a9f5fddfad3dfc0a8f36b10358567e", size = 6679168, upload-time = "2026-08-09T13:46:12.275Z" }, + { url = "https://files.pythonhosted.org/packages/c4/3b/ecd49dd90033cceb2704d88ca905d4d7d89b0e8c739608754ffd325fa820/numpy-2.5.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:50e500dc868e9313530ce12ba470fe50ff3afe3d62993ed6eff652dacd555b65", size = 15624501, upload-time = "2026-08-09T13:46:15.322Z" }, + { url = "https://files.pythonhosted.org/packages/c7/99/461bd36dbdfac6c1c53efa370bd55a83227542d0d118f1677dbf1a3dacd5/numpy-2.5.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318b9a4c845dbea06708a29c84ee429cc3065048db34cdb799047643492050ee", size = 16713701, upload-time = "2026-08-09T13:46:18.949Z" }, + { url = "https://files.pythonhosted.org/packages/f9/9c/2b251df9e8a5d647b62b0cbc1b90a91850c1cf4859ecb532fd0b4eacff6c/numpy-2.5.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:34c319e2963be042673fb46570501b2f06c41924e17e3563d58646b4380dfb68", size = 16986065, upload-time = "2026-08-09T13:46:23.006Z" }, + { url = "https://files.pythonhosted.org/packages/8f/25/20de43f53ff1390534a124475055a19f01fe10c920a0fd11b8e18d6d6052/numpy-2.5.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f06571a052127dc1b4e8b83029b4d1b20daa2b64a31cdd181fc6bc774e9000eb", size = 18470031, upload-time = "2026-08-09T13:46:27.102Z" }, + { url = "https://files.pythonhosted.org/packages/56/5e/0c577ca308d6da5eb79b546ba10bbe5b60148192194e2da060913b1de4f1/numpy-2.5.2-cp314-cp314-win32.whl", hash = "sha256:2cc779226e476d1e1f08c74068c419e60f41a9e0e069c92f6671d31d5c985e98", size = 6121028, upload-time = "2026-08-09T13:46:30.046Z" }, + { url = "https://files.pythonhosted.org/packages/15/5c/7bcbd5b11f94199073320410cddcbb80cee62415bfeb540874b265c2d922/numpy-2.5.2-cp314-cp314-win_amd64.whl", hash = "sha256:7587f53dfbd5edc0f7b87c6217b4c6d2d1f2ef9c3da70bc1315e7db5f8d7ec9d", size = 12597627, upload-time = "2026-08-09T13:46:32.886Z" }, + { url = "https://files.pythonhosted.org/packages/87/bc/4d0b06fba0da90ccc75af62823cb9dcedb6c9ea0cffa058cb2c9ee773a77/numpy-2.5.2-cp314-cp314-win_arm64.whl", hash = "sha256:3e4c367352d3747784248a227fbec218e193b56f7e6692e3b64fc805478ecfdf", size = 10680414, upload-time = "2026-08-09T13:46:36.036Z" }, + { url = "https://files.pythonhosted.org/packages/cd/17/f429aac9dc08833a0d0f188eba38c532a751b1a1f2ca6018a37b455cb321/numpy-2.5.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b879fb674276e331513fb136b78dbc6bd3c848309e0d841cfd63be3896c4cfc1", size = 12026967, upload-time = "2026-08-09T13:46:39.084Z" }, + { url = "https://files.pythonhosted.org/packages/ca/9f/d0849de96a2a4ceaa16662f18ee13eaa9c0aa418269fdc8c4857c56b11da/numpy-2.5.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:fd0d703772bba096843785bd38371e31bb4a0c1151497ad5739d182114a73f7f", size = 5473874, upload-time = "2026-08-09T13:46:42.075Z" }, + { url = "https://files.pythonhosted.org/packages/89/3c/8df216d4a4a5422a3de045301cf7df8ea47286d76f5cb7160b0128ac26b7/numpy-2.5.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:3a2f061cebd9e3d23bdcfaaded5e2293a4c6a5b60fa42df85d410a725ce621bf", size = 6789276, upload-time = "2026-08-09T13:46:44.387Z" }, + { url = "https://files.pythonhosted.org/packages/e6/3a/20d7e9891c4ddfadd6ff8d95bf4b29f353d8e1770553de2099880551dfb9/numpy-2.5.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6df895598c0edcb41030126c89e0f353b07d93238116143b7405e937359736c4", size = 15659154, upload-time = "2026-08-09T13:46:47.538Z" }, + { url = "https://files.pythonhosted.org/packages/aa/d6/f3aa3d2688bf501b858835c6bd087ae9b51a56ae6fca8e2b0990abd177af/numpy-2.5.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1ab3d4a901f844ea836c3e80bf463c6a27d7f3c14e8e292fcf28d348b25b9bce", size = 16748909, upload-time = "2026-08-09T13:46:51.442Z" }, + { url = "https://files.pythonhosted.org/packages/7d/8f/1c5cae8d2baf86ab802ae97a00be55bc7e21ebc11b12bbc33376c5f05342/numpy-2.5.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:cebc2d6dbb605a7703d59751dea4bd6b0ab127a5a4338a6f432df1936fef8b26", size = 17027685, upload-time = "2026-08-09T13:46:55.095Z" }, + { url = "https://files.pythonhosted.org/packages/5c/27/71d3467404aedc1c24ce79610f91b52b0b0f466c43a701aa56fc75c145ab/numpy-2.5.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:eaca7ff36f0f52e2111ec71f169d8fd3e889e7ddc0d2592e0d703fd8d3ce8fac", size = 18501181, upload-time = "2026-08-09T13:46:59.09Z" }, + { url = "https://files.pythonhosted.org/packages/14/2f/42921d27c40aea7e077f4a423ae509fd9220b028cd787bafefd8ab2b3a5f/numpy-2.5.2-cp314-cp314t-win32.whl", hash = "sha256:ddf47472af2e4280d79bac82304f5e80150211f1b9e614b760061d5fdfbb6eba", size = 6271085, upload-time = "2026-08-09T13:47:01.903Z" }, + { url = "https://files.pythonhosted.org/packages/75/e6/bad5f5d56de9b1971bac959963dda276d35c40f1854475005434bbe08692/numpy-2.5.2-cp314-cp314t-win_amd64.whl", hash = "sha256:44ef9675d908e65f9953063837c3277730f3f4437615a4cdab67b366cabaf884", size = 12787971, upload-time = "2026-08-09T13:47:04.963Z" }, + { url = "https://files.pythonhosted.org/packages/df/05/f608795cb34391acd67e38d94a3c36abd8d8576293a3a80727d7595c372c/numpy-2.5.2-cp314-cp314t-win_arm64.whl", hash = "sha256:eaa088384c46f519dacb93b7ec483a6d6b19a4a2085ae4f25ab9b1c43d387d1e", size = 10750306, upload-time = "2026-08-09T13:47:07.976Z" }, + { url = "https://files.pythonhosted.org/packages/33/c6/28de0191c5f82b7d42a0a51390ba98587048aa93a39fafb05bdbe6e8d00c/numpy-2.5.2-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:078f9b027b478c9379b9677babbf0f8b8f1ecfada27636d7b9a93990c638739f", size = 16885274, upload-time = "2026-08-09T13:47:11.439Z" }, + { url = "https://files.pythonhosted.org/packages/dd/d1/973ca116000d244897e468ea1aff30b589e5022e3c8744b71706fe33bd57/numpy-2.5.2-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:50a68f4bacd8a2b33d8da3d2269d0d78500f86ea582e4786dc10f5ef2c2c6842", size = 11907846, upload-time = "2026-08-09T13:47:15.128Z" }, + { url = "https://files.pythonhosted.org/packages/78/d9/8c4b3937ef204cb2fd88d389ccd0f265a2ffb11f35a01d2064cf46714bd6/numpy-2.5.2-cp315-cp315-macosx_14_0_arm64.whl", hash = "sha256:e79aba74ffaf5f78a050d777c184cddf8fdffabab38acf5f3ef1fecbc17895d6", size = 5354892, upload-time = "2026-08-09T13:47:18.07Z" }, + { url = "https://files.pythonhosted.org/packages/74/9b/b6ee65ea2999fdb7023935e108e6fb776ee4082aa15f159acfa857e578c8/numpy-2.5.2-cp315-cp315-macosx_14_0_x86_64.whl", hash = "sha256:9a0731745a72a184490a582fb4af2533512bd071ace67785b5fdffc0ae58dce8", size = 6679309, upload-time = "2026-08-09T13:47:20.456Z" }, + { url = "https://files.pythonhosted.org/packages/43/f3/acb18d8b137a393c8e7803a8c994c9e64bde3930692a69d826993113a159/numpy-2.5.2-cp315-cp315-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4ec954036759bcee3aa484f8603bd9c14f3e776293b85578b8734c2d72777c69", size = 15625850, upload-time = "2026-08-09T13:47:24.365Z" }, + { url = "https://files.pythonhosted.org/packages/a9/bf/a8e9bb0db815a0e265b5744ebedd3af0bd5faad8604e5b50a1cd012f3c91/numpy-2.5.2-cp315-cp315-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc649493697006bc90614a5f0bbc8cb3cb1866715c474e473694968d7e6b99ab", size = 16713664, upload-time = "2026-08-09T13:47:27.965Z" }, + { url = "https://files.pythonhosted.org/packages/0c/c3/6e913736b3dd6582344af32418b5fb9dab34282e8a8174ae1d54ceb0fc13/numpy-2.5.2-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:cf7de32f486e4ac9e2d93b810f9e9ac72a728dd46a32a0bb403222f27f653514", size = 16986749, upload-time = "2026-08-09T13:47:31.541Z" }, + { url = "https://files.pythonhosted.org/packages/80/09/7d3b23eff5c7428ef6c01e6f7052bb60d504c4d33e317b36b8959c24ad97/numpy-2.5.2-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:2ffa7bacab3e2ee1b19ed31766bb60bb380b68c23f051e199c5cc598afd68710", size = 18470495, upload-time = "2026-08-09T13:47:35.364Z" }, + { url = "https://files.pythonhosted.org/packages/a5/a4/68a321d825374f6eb677ffe8ef8c6b9a328304e6fd2e39d9530822776607/numpy-2.5.2-cp315-cp315-win32.whl", hash = "sha256:6b588cc8f902d6bff201c19fd00c43ab8545671e3554d014e12e14139e5e8617", size = 6120696, upload-time = "2026-08-09T13:47:38.561Z" }, + { url = "https://files.pythonhosted.org/packages/c8/23/deafbb1700f79fae9cd1e91220f133d124cc267de1b584da3fbf6db2f6cd/numpy-2.5.2-cp315-cp315-win_amd64.whl", hash = "sha256:07d4e89f3a9ab0a9ba24264ccdb642b3dd951b2281e8883a5481a4aa79cc31a7", size = 12597324, upload-time = "2026-08-09T13:47:41.401Z" }, + { url = "https://files.pythonhosted.org/packages/33/cd/3272ba105e3bbbdaeb11357eda31e7a6825ffe159e8171665660299a948f/numpy-2.5.2-cp315-cp315-win_arm64.whl", hash = "sha256:a610dc7e3c52edd39c2bc2375ff9c3fd59cb3ad00e4472d36f83bc1457145788", size = 10680466, upload-time = "2026-08-09T13:47:44.873Z" }, + { url = "https://files.pythonhosted.org/packages/0e/0e/58370637b1bb70a5c9ce2b43f4b521ccb224e36ccb76a6596b17ae4b447c/numpy-2.5.2-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:40f4d451aed46a8046a1aae41c4e55fb3612273df9c502480135e1501576a34b", size = 16993947, upload-time = "2026-08-09T13:47:48.97Z" }, + { url = "https://files.pythonhosted.org/packages/10/93/2abcb807712b289d6d60fe4cf30532f98974a8396d885650f3ba5a13026e/numpy-2.5.2-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:c081cbe16ba1ab53078e5ff29013621e33c509eedab055775d956427712c236e", size = 12025331, upload-time = "2026-08-09T13:47:52.646Z" }, + { url = "https://files.pythonhosted.org/packages/8b/3a/2898e003a5fbaf87e76c039b4ee1f5eb390471b4ffe74887c1f34c4e791e/numpy-2.5.2-cp315-cp315t-macosx_14_0_arm64.whl", hash = "sha256:0090ccdd57ec2703e9b49d0bf554767370581c1dd0a6b2bb2b2d9def317d042a", size = 5472336, upload-time = "2026-08-09T13:47:55.403Z" }, + { url = "https://files.pythonhosted.org/packages/61/a5/23f69d07c544597b29758b31b55c27dc9d541012a2c1496189fef702aec2/numpy-2.5.2-cp315-cp315t-macosx_14_0_x86_64.whl", hash = "sha256:6a9bb119fb8dd21ba30b3f0e555b7e2b081bd9883af21ec9c1c633d161cda3a8", size = 6788387, upload-time = "2026-08-09T13:47:58.192Z" }, + { url = "https://files.pythonhosted.org/packages/15/ea/c0dbdbcf22f43782510a3e492dd3da73c6112b69cac8929d16d127536fc4/numpy-2.5.2-cp315-cp315t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a839318485284a6fb31be4f8f2c91c8f2cb22f4543c4a8903f12b0671ffe07cc", size = 15667096, upload-time = "2026-08-09T13:48:01.562Z" }, + { url = "https://files.pythonhosted.org/packages/fc/5e/29c73c31748cdb0f7566642125ba17fd5b56780cddf891b085dab27e4466/numpy-2.5.2-cp315-cp315t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba0a474801b8dc67b66bf465548abc90e82b44d2611b5770f33008dcabffe8ec", size = 16751730, upload-time = "2026-08-09T13:48:05.706Z" }, + { url = "https://files.pythonhosted.org/packages/47/95/02501e8454796bb58dadf7a99d3181e0b464bf264e1003039572f9779fac/numpy-2.5.2-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:0a4035ae1129ff8777f08bfbd44f1e5d8e9c049ce0c2dd78fc0d92c13e7251c0", size = 17038686, upload-time = "2026-08-09T13:48:09.627Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b5/53a681d91b5c82687067d8ea5035e02d917b5509d6f334cb06484a954714/numpy-2.5.2-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:77843ca236b777e67f8d6b3660ea116e499612703a0ecd7093f316201eb9d8e2", size = 18507727, upload-time = "2026-08-09T13:48:13.744Z" }, + { url = "https://files.pythonhosted.org/packages/42/06/6e11443f7b64ee376c860506091103bf68f92d2cab9e8d96d4501babf07c/numpy-2.5.2-cp315-cp315t-win32.whl", hash = "sha256:7354826bc6f8f69402e9b7fe28d15fcd34feebd74f856f111585c5b0c9fb0251", size = 6269775, upload-time = "2026-08-09T13:48:17.543Z" }, + { url = "https://files.pythonhosted.org/packages/f1/18/195d6b86cd72dbbc501edfa778005fa6b87afd34c153e46028cd3a0938f4/numpy-2.5.2-cp315-cp315t-win_amd64.whl", hash = "sha256:e5651f3f87add730ee6608d915009e19c911fba0cb000c7e3ea994b7d768eb12", size = 12782559, upload-time = "2026-08-09T13:48:21.023Z" }, + { url = "https://files.pythonhosted.org/packages/b4/07/458c344f0f0c178f4481dad5cca790626ffe4c34eabf9467069d06ee4999/numpy-2.5.2-cp315-cp315t-win_arm64.whl", hash = "sha256:5f8e00be2ec6f45f4e8a41a527f68d44a7d96fee92a650e4d8b1326f77f61e6e", size = 10748103, upload-time = "2026-08-09T13:48:24.21Z" }, +] + +[[package]] +name = "orjson" +version = "3.12.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/f3/742fb1f62b825f2c010697eaf4e828004bc2a81e7e806666989c132c7c42/orjson-3.12.0.tar.gz", hash = "sha256:d14203fb1aae2ad9b3d52f8a0e82aeb10197ef1c9bc61da7f358bd70b00123d5", size = 4142915, upload-time = "2026-08-14T16:13:30.607Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/4a/295da39c651c2faac8bd351a2a346f0fdedd9d50b847ee9dfc27d2207ef6/orjson-3.12.0-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:aa3e43a6846e91d7bde3d5a9c66090fcd8744f569a9b6cffc5e1ca38f6a461c0", size = 223427, upload-time = "2026-08-14T16:12:28.525Z" }, + { url = "https://files.pythonhosted.org/packages/29/98/758cf90fbeaaafb7f8141bfac75a432099959f3a2f5db93a412e876415d8/orjson-3.12.0-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:11edb4660a6680abee9788a3a9072208a2c96538cc1322bd79542065229d8e54", size = 123725, upload-time = "2026-08-14T16:12:30.013Z" }, + { url = "https://files.pythonhosted.org/packages/32/b5/5b934d251f8651f7e41df180ad0c57a6e1cabe15c7bd331638413a50ebc9/orjson-3.12.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:2d3a9da945a4d96ae758fdaaca56742e6b73b6fd554c5d8876f252a6dad70b83", size = 113375, upload-time = "2026-08-14T16:12:31.209Z" }, + { url = "https://files.pythonhosted.org/packages/cd/d2/37efb5b12a176ce3ced29f4144f20da57d02757f78ce549637dc1b4e1fc8/orjson-3.12.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:92ffc09e07233a6ab6d4e067f7841edcbcc134cb4812155cf171ea5255a421d7", size = 129983, upload-time = "2026-08-14T16:12:32.721Z" }, + { url = "https://files.pythonhosted.org/packages/50/22/0644b87c73f13e0092df8f35a1fe280d991e5e90072087411e0dd7e44e0c/orjson-3.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf44e374aadde77b1f6109f1030be51433eb61984379852766b6f4e187db7b1e", size = 130629, upload-time = "2026-08-14T16:12:34.084Z" }, + { url = "https://files.pythonhosted.org/packages/8c/57/80b986ebfecd9c6a177ddf1c2319717f0cd8feffb2b78946595a18a2fc88/orjson-3.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1192a7021b6d071aaf909864f6e924d6a2675ca360485b972b8401749311750b", size = 131245, upload-time = "2026-08-14T16:12:35.713Z" }, + { url = "https://files.pythonhosted.org/packages/80/3d/75c5ac5a69161f44492a68fbdde66f4cc4ce48cd5e1fb05918e46f0c8848/orjson-3.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:53c0c474a9d9aff9aebfc0c88de1f28f843d940e6e3a80729abdf6a20274356f", size = 135397, upload-time = "2026-08-14T16:12:37.128Z" }, + { url = "https://files.pythonhosted.org/packages/71/93/4d71f2df314a97ff0d27a4559bf5888fc8406e3c6dec90e92291e3511215/orjson-3.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:532ff8cd4bd59a327a953a7dcde922c7fc25b85e29721bb8633265430d3a3873", size = 127693, upload-time = "2026-08-14T16:12:38.627Z" }, + { url = "https://files.pythonhosted.org/packages/bc/1d/0dbc6be5adfd1730491072fb60beb6bcdf5d7b2596ee41b7fc2e298bfc09/orjson-3.12.0-cp312-cp312-win32.whl", hash = "sha256:a6cf4b18e7de173f209f2084ffbd736dd72389a396326ee80a7022168be232e5", size = 128000, upload-time = "2026-08-14T16:12:39.954Z" }, + { url = "https://files.pythonhosted.org/packages/2d/c9/97b1ce0112ebf5e949c775ed5b1755e562233179f3584579673cc24d6378/orjson-3.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:010811c1b69773450a01cef97727a67b223242f350b77d4ca000e59a9ef2155a", size = 122106, upload-time = "2026-08-14T16:12:41.324Z" }, + { url = "https://files.pythonhosted.org/packages/a8/6a/facd8b312e4a0d3a7fa978c7e15821f74a336adf1d65529faec33b48e18b/orjson-3.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:ad29eece0c601737f2a60edc2752a84e7a0785df3efb62e3012834700a5afe0d", size = 126869, upload-time = "2026-08-14T16:12:42.651Z" }, + { url = "https://files.pythonhosted.org/packages/54/cb/d7b78218a987eb8a8ce4eeae0286b1bb679333eb631ea0eeaf6371680bfc/orjson-3.12.0-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9a36ec60f1796f9a3f13e3b98390295e17a1c7c10155b448d264098bf9ee5900", size = 223397, upload-time = "2026-08-14T16:12:44.003Z" }, + { url = "https://files.pythonhosted.org/packages/f8/4a/bc87c45e7ec639d35ebefd62618e01939531ac8e171426606a01bda05914/orjson-3.12.0-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:ad0422b92d5195443a39f80c3bcf731cc2e00f153bd32063a47b73b057bd0f03", size = 123662, upload-time = "2026-08-14T16:12:45.433Z" }, + { url = "https://files.pythonhosted.org/packages/94/ee/c9a4ff3f2dbedbbe9e635d0fa72c8866adede09b6335ef9644f53752f0d8/orjson-3.12.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:5a0fdbc216388f653d3752ff310e710f59253bd4ed6a2bfb3f4f06b84714bbd8", size = 113374, upload-time = "2026-08-14T16:12:46.755Z" }, + { url = "https://files.pythonhosted.org/packages/75/09/3f330a026a796c8b4c97a6f429652a5e912e7065039bf96ed25e42aa7b25/orjson-3.12.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:2eb5c56e534127b2b8fa38d2363c8b1b8190367ee0d1d16c041517d880843b94", size = 130029, upload-time = "2026-08-14T16:12:48.06Z" }, + { url = "https://files.pythonhosted.org/packages/7d/40/094cc53126a3d22f76cdf83b6ea67338bed01d774037621a785aa8e6e5ea/orjson-3.12.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:784106539f4b9d4b930e0b4eb8d45168507dae001945e71b4675a367f1e5e806", size = 130528, upload-time = "2026-08-14T16:12:49.362Z" }, + { url = "https://files.pythonhosted.org/packages/bc/74/89bb236deb9565f99434b13052bb40ddfcce4adf3afbfa3132ee7e421468/orjson-3.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c680706fc8396d95e7c4c1f9482563f552137aef91b57237a3ad5aaf64629df", size = 131075, upload-time = "2026-08-14T16:12:50.692Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ac/1176360d762c01b5bd34acd56fc098e936c491363d8b6b397ad4aa475547/orjson-3.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:83445adc40cba26d6d621185a45128ce455b766af368cad2ab64b970603a7978", size = 135321, upload-time = "2026-08-14T16:12:52.114Z" }, + { url = "https://files.pythonhosted.org/packages/7a/02/bbd881c8b9276d50b998de38b4e97de8ace1aac940b0ee545aedbf65ed00/orjson-3.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:644d005bc82f917337a95ce270c9f6f92f9834c2bed7b1477572f8db00784222", size = 127472, upload-time = "2026-08-14T16:12:53.517Z" }, + { url = "https://files.pythonhosted.org/packages/8e/02/a0934d7503e6dcbedd6afac3e7f3f8597fd09389949ad94d0f7540e9dbca/orjson-3.12.0-cp313-cp313-win32.whl", hash = "sha256:d8e78d3d93705e3d27cc17cdb209e44d7a8ea203010cac6ce9c7ffc1ae1996f1", size = 128000, upload-time = "2026-08-14T16:12:55.14Z" }, + { url = "https://files.pythonhosted.org/packages/52/87/69f98f8d40faff103a965a5fbb83f08241b01beaf92badb5413fbc9358cc/orjson-3.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:b85931be5b6763c31283805c9bdaae1ca03ad9f6f12a15f1cbf6745b907932c2", size = 121841, upload-time = "2026-08-14T16:12:56.507Z" }, + { url = "https://files.pythonhosted.org/packages/e6/07/b83046a4e3cadcc0987d0f160696107c4af706a619b56e4ad01940cadadf/orjson-3.12.0-cp313-cp313-win_arm64.whl", hash = "sha256:6a31348d7dfa64cd9c78bd1f510ff44c48fe64d71094e6b90e364dba3b55949e", size = 126765, upload-time = "2026-08-14T16:12:57.806Z" }, + { url = "https://files.pythonhosted.org/packages/12/9d/3931253e6f3148abf2cbe14830367042a4806b362ea520df2303db188fb9/orjson-3.12.0-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9e6fee342a48760e854d743e7a81534d8e2925a6f46e09f750cf56b50fd1de5d", size = 223391, upload-time = "2026-08-14T16:12:59.184Z" }, + { url = "https://files.pythonhosted.org/packages/8a/0e/b4a4f1e305367245877b967a0bad70fcf001d77c54ac4339a120b66fdae4/orjson-3.12.0-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:8c3bb86dd10f39b3fbf434b7d5dc7cac77d6fc8ac572ae30a10731ede2c4b647", size = 123659, upload-time = "2026-08-14T16:13:00.548Z" }, + { url = "https://files.pythonhosted.org/packages/96/f3/6782c6fa85e2702bc66be183c3b421486167dcf266ee4dc1403fe3824870/orjson-3.12.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:2bb3ce43203936072dd8b4917b01d3aecfc02329bfb42510cb7cfb24708adc9c", size = 113337, upload-time = "2026-08-14T16:13:02.009Z" }, + { url = "https://files.pythonhosted.org/packages/bf/79/b32ab64bacda9d0fa4942ef483bd03cabf0eaf2be819ca9fb7ff610c559d/orjson-3.12.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:6a2a79c89984dc719817d388c8709e0efc2a2795a934eaa746b4882eb6045adc", size = 130112, upload-time = "2026-08-14T16:13:03.404Z" }, + { url = "https://files.pythonhosted.org/packages/ee/49/6e6142999ca01509219be5e5a9c338a3e5ea011f63e91ff473fbbf3734ed/orjson-3.12.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f06dd838d1e07d9b1de0932ec0485ec92c4d5f5d1ad4817a656268c3e88be1e1", size = 130520, upload-time = "2026-08-14T16:13:04.798Z" }, + { url = "https://files.pythonhosted.org/packages/49/d0/3745af0a4cc9867784f29722929cec4d10bd1c877cd754b01ba6d96eb21a/orjson-3.12.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6b11be792c3d2c6a4be2af4ebf97a68d0bf5f580aca6e86a418a354f6cc846a", size = 131053, upload-time = "2026-08-14T16:13:06.14Z" }, + { url = "https://files.pythonhosted.org/packages/c3/f4/6fe5a22fa478fffb190e65c338c84df5c311ef597b363150a17cc57063c0/orjson-3.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:477ecaf6b9f88f873341b91fcc736119ca81b5e002a9f7f308ff5b4f2ce2a70e", size = 135321, upload-time = "2026-08-14T16:13:07.544Z" }, + { url = "https://files.pythonhosted.org/packages/ff/41/b1b0ec30289646a81a76e2dbaae2686b96fcccb7cb0323dc1dd78cbc7875/orjson-3.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f3c0683136acdc29afdf88a5bc2f7d3d0e34087788d1d63c0144b805a87a196f", size = 127485, upload-time = "2026-08-14T16:13:08.88Z" }, + { url = "https://files.pythonhosted.org/packages/bf/2b/277404bdcc21c93b112b963655b76443ebfe828f8a3ff1de7d90f8850eb3/orjson-3.12.0-cp314-cp314-win32.whl", hash = "sha256:d39f3f5c3927e2dc0913fe5bbc1a2f6b1b9d1bba1de6358340d0ad0d0c00ca92", size = 128048, upload-time = "2026-08-14T16:13:10.305Z" }, + { url = "https://files.pythonhosted.org/packages/41/2b/395b36fa2b4ce7af70b651d715e88f80d884b2c2b14a6b53e84d554fb5f0/orjson-3.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:0b1ac5bf6609b2716c7954011c5fef6254922df029f45d032ee4ebf5d363cbed", size = 121858, upload-time = "2026-08-14T16:13:11.634Z" }, + { url = "https://files.pythonhosted.org/packages/ea/a3/833e895ff452859eebe75093d26691fe9108f1a7a6a08435d7a5780ea652/orjson-3.12.0-cp314-cp314-win_arm64.whl", hash = "sha256:50fae885cb073eac7556353ff3df93312b0d5137b0a5056b2bb63f97ed9a93c7", size = 126749, upload-time = "2026-08-14T16:13:13.117Z" }, + { url = "https://files.pythonhosted.org/packages/58/64/99c8947ece10c17176af9aae85c4948f1d109da77440ec14d87239efaf73/orjson-3.12.0-cp315-cp315-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:01efac2074fffb4cb1ea3fab7861e9d0f2a26913854a972f5ac760525dbdaf6e", size = 223398, upload-time = "2026-08-14T16:13:14.694Z" }, + { url = "https://files.pythonhosted.org/packages/3e/30/cf983fe09f2731420fda097a9f7ef4343f47fa216c228961ad8f6da44f3d/orjson-3.12.0-cp315-cp315-macosx_15_0_arm64.whl", hash = "sha256:ed4ca42bd55955aa34deedcfdfd0e0c31abf51143aae158ae2bc3520b626e517", size = 123655, upload-time = "2026-08-14T16:13:16.221Z" }, + { url = "https://files.pythonhosted.org/packages/11/50/9cb8ae73fa4749dbbc20f617004213b5ff01c20aaeec34c3f31124f2c1d8/orjson-3.12.0-cp315-cp315-manylinux_2_39_aarch64.whl", hash = "sha256:40f92192227505acca4e2533ce565f8e6b9535f7d0d09b0968452f18b7376b38", size = 130515, upload-time = "2026-08-14T16:13:17.601Z" }, + { url = "https://files.pythonhosted.org/packages/9f/0a/adb6ce1a5b5fbf9cb1790f9961bb668a0dd5429aadaf6cee044724681795/orjson-3.12.0-cp315-cp315-manylinux_2_39_armv7l.whl", hash = "sha256:33efefcf5d88eaf400b47e2eba02f91f319bb9951be61ca500b7d536d3f2079d", size = 113327, upload-time = "2026-08-14T16:13:18.927Z" }, + { url = "https://files.pythonhosted.org/packages/51/5c/d17f61581d8dbdde7048f87a330fa24915edec38db4d72b381fec14fbb56/orjson-3.12.0-cp315-cp315-manylinux_2_39_i686.whl", hash = "sha256:8e386b0bc0ddd7cd2056f884b5a0af33592bd01ac66a7ca4b42a65a7e7774a13", size = 130105, upload-time = "2026-08-14T16:13:20.317Z" }, + { url = "https://files.pythonhosted.org/packages/9f/b7/938befcf33bee4704a92ecec6a2731224c539d939bf9429fd39396d28931/orjson-3.12.0-cp315-cp315-manylinux_2_39_x86_64.whl", hash = "sha256:58c58e1de0006ffb580368d6793c36c7b0b021db066479cf281bf5061e732328", size = 131049, upload-time = "2026-08-14T16:13:21.719Z" }, + { url = "https://files.pythonhosted.org/packages/b0/15/cfa2021d64d5aa8bb5c9f604ef375e00ec8b657651b5dd650b1b7ad13df1/orjson-3.12.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:08231552159be266a7269555bd9f7c016aee7d9ad6dab06eb58796c5ccb7101c", size = 135320, upload-time = "2026-08-14T16:13:23.415Z" }, + { url = "https://files.pythonhosted.org/packages/1a/50/3e75dfe357c1e8f9e287c7a5740260ef15bd23a5299eae8d0835dcad5375/orjson-3.12.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:a15f9a891bce5f5cc5d210e3ad8614d4d1b489a56448c099d6d2a7168b2d954a", size = 127488, upload-time = "2026-08-14T16:13:24.791Z" }, + { url = "https://files.pythonhosted.org/packages/11/a6/79aed402eb3ab284dc5b4791a7ad62c5875127de01b8e3f04bd92d551298/orjson-3.12.0-cp315-cp315-win32.whl", hash = "sha256:03091c8a64db4be38746597ceea68f33c238e27acd9bfe99fb59420224ae7a55", size = 128048, upload-time = "2026-08-14T16:13:26.217Z" }, + { url = "https://files.pythonhosted.org/packages/64/f7/2723e264aab7248c1ed6ecaad8e5d0cb866c0cffde75442102ffa7491aba/orjson-3.12.0-cp315-cp315-win_amd64.whl", hash = "sha256:2b7bcefb9f40fa242fa6b06377232c048e655747790829609168c01162f60578", size = 121860, upload-time = "2026-08-14T16:13:27.577Z" }, + { url = "https://files.pythonhosted.org/packages/82/56/630c9113ec8996778f1f0304b364b091b9a9db5fef5fdc17cca622f5ea24/orjson-3.12.0-cp315-cp315-win_arm64.whl", hash = "sha256:859fc4196855890150bb08e649b30d2c93b249b3e3edd0d3bb2231abf8aa8adc", size = 126754, upload-time = "2026-08-14T16:13:28.962Z" }, +] + +[[package]] +name = "ormsgpack" +version = "1.12.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/12/0c/f1761e21486942ab9bb6feaebc610fa074f7c5e496e6962dea5873348077/ormsgpack-1.12.2.tar.gz", hash = "sha256:944a2233640273bee67521795a73cf1e959538e0dfb7ac635505010455e53b33", size = 39031, upload-time = "2026-01-18T20:55:28.023Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4c/36/16c4b1921c308a92cef3bf6663226ae283395aa0ff6e154f925c32e91ff5/ormsgpack-1.12.2-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7a29d09b64b9694b588ff2f80e9826bdceb3a2b91523c5beae1fab27d5c940e7", size = 378618, upload-time = "2026-01-18T20:55:50.835Z" }, + { url = "https://files.pythonhosted.org/packages/c0/68/468de634079615abf66ed13bb5c34ff71da237213f29294363beeeca5306/ormsgpack-1.12.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b39e629fd2e1c5b2f46f99778450b59454d1f901bc507963168985e79f09c5d", size = 203186, upload-time = "2026-01-18T20:56:11.163Z" }, + { url = "https://files.pythonhosted.org/packages/73/a9/d756e01961442688b7939bacd87ce13bfad7d26ce24f910f6028178b2cc8/ormsgpack-1.12.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:958dcb270d30a7cb633a45ee62b9444433fa571a752d2ca484efdac07480876e", size = 210738, upload-time = "2026-01-18T20:56:09.181Z" }, + { url = "https://files.pythonhosted.org/packages/7b/ba/795b1036888542c9113269a3f5690ab53dd2258c6fb17676ac4bd44fcf94/ormsgpack-1.12.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58d379d72b6c5e964851c77cfedfb386e474adee4fd39791c2c5d9efb53505cc", size = 212569, upload-time = "2026-01-18T20:56:06.135Z" }, + { url = "https://files.pythonhosted.org/packages/6c/aa/bff73c57497b9e0cba8837c7e4bcab584b1a6dbc91a5dd5526784a5030c8/ormsgpack-1.12.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8463a3fc5f09832e67bdb0e2fda6d518dc4281b133166146a67f54c08496442e", size = 387166, upload-time = "2026-01-18T20:55:36.738Z" }, + { url = "https://files.pythonhosted.org/packages/d3/cf/f8283cba44bcb7b14f97b6274d449db276b3a86589bdb363169b51bc12de/ormsgpack-1.12.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:eddffb77eff0bad4e67547d67a130604e7e2dfbb7b0cde0796045be4090f35c6", size = 482498, upload-time = "2026-01-18T20:55:29.626Z" }, + { url = "https://files.pythonhosted.org/packages/05/be/71e37b852d723dfcbe952ad04178c030df60d6b78eba26bfd14c9a40575e/ormsgpack-1.12.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fcd55e5f6ba0dbce624942adf9f152062135f991a0126064889f68eb850de0dd", size = 425518, upload-time = "2026-01-18T20:55:49.556Z" }, + { url = "https://files.pythonhosted.org/packages/7a/0c/9803aa883d18c7ef197213cd2cbf73ba76472a11fe100fb7dab2884edf48/ormsgpack-1.12.2-cp312-cp312-win_amd64.whl", hash = "sha256:d024b40828f1dde5654faebd0d824f9cc29ad46891f626272dd5bfd7af2333a4", size = 117462, upload-time = "2026-01-18T20:55:47.726Z" }, + { url = "https://files.pythonhosted.org/packages/c8/9e/029e898298b2cc662f10d7a15652a53e3b525b1e7f07e21fef8536a09bb8/ormsgpack-1.12.2-cp312-cp312-win_arm64.whl", hash = "sha256:da538c542bac7d1c8f3f2a937863dba36f013108ce63e55745941dda4b75dbb6", size = 111559, upload-time = "2026-01-18T20:55:54.273Z" }, + { url = "https://files.pythonhosted.org/packages/eb/29/bb0eba3288c0449efbb013e9c6f58aea79cf5cb9ee1921f8865f04c1a9d7/ormsgpack-1.12.2-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:5ea60cb5f210b1cfbad8c002948d73447508e629ec375acb82910e3efa8ff355", size = 378661, upload-time = "2026-01-18T20:55:57.765Z" }, + { url = "https://files.pythonhosted.org/packages/6e/31/5efa31346affdac489acade2926989e019e8ca98129658a183e3add7af5e/ormsgpack-1.12.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3601f19afdbea273ed70b06495e5794606a8b690a568d6c996a90d7255e51c1", size = 203194, upload-time = "2026-01-18T20:56:08.252Z" }, + { url = "https://files.pythonhosted.org/packages/eb/56/d0087278beef833187e0167f8527235ebe6f6ffc2a143e9de12a98b1ce87/ormsgpack-1.12.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29a9f17a3dac6054c0dce7925e0f4995c727f7c41859adf9b5572180f640d172", size = 210778, upload-time = "2026-01-18T20:55:17.694Z" }, + { url = "https://files.pythonhosted.org/packages/1c/a2/072343e1413d9443e5a252a8eb591c2d5b1bffbe5e7bfc78c069361b92eb/ormsgpack-1.12.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39c1bd2092880e413902910388be8715f70b9f15f20779d44e673033a6146f2d", size = 212592, upload-time = "2026-01-18T20:55:32.747Z" }, + { url = "https://files.pythonhosted.org/packages/a2/8b/a0da3b98a91d41187a63b02dda14267eefc2a74fcb43cc2701066cf1510e/ormsgpack-1.12.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:50b7249244382209877deedeee838aef1542f3d0fc28b8fe71ca9d7e1896a0d7", size = 387164, upload-time = "2026-01-18T20:55:40.853Z" }, + { url = "https://files.pythonhosted.org/packages/19/bb/6d226bc4cf9fc20d8eb1d976d027a3f7c3491e8f08289a2e76abe96a65f3/ormsgpack-1.12.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:5af04800d844451cf102a59c74a841324868d3f1625c296a06cc655c542a6685", size = 482516, upload-time = "2026-01-18T20:55:42.033Z" }, + { url = "https://files.pythonhosted.org/packages/fb/f1/bb2c7223398543dedb3dbf8bb93aaa737b387de61c5feaad6f908841b782/ormsgpack-1.12.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cec70477d4371cd524534cd16472d8b9cc187e0e3043a8790545a9a9b296c258", size = 425539, upload-time = "2026-01-18T20:55:24.727Z" }, + { url = "https://files.pythonhosted.org/packages/7b/e8/0fb45f57a2ada1fed374f7494c8cd55e2f88ccd0ab0a669aa3468716bf5f/ormsgpack-1.12.2-cp313-cp313-win_amd64.whl", hash = "sha256:21f4276caca5c03a818041d637e4019bc84f9d6ca8baa5ea03e5cc8bf56140e9", size = 117459, upload-time = "2026-01-18T20:55:56.876Z" }, + { url = "https://files.pythonhosted.org/packages/7a/d4/0cfeea1e960d550a131001a7f38a5132c7ae3ebde4c82af1f364ccc5d904/ormsgpack-1.12.2-cp313-cp313-win_arm64.whl", hash = "sha256:baca4b6773d20a82e36d6fd25f341064244f9f86a13dead95dd7d7f996f51709", size = 111577, upload-time = "2026-01-18T20:55:43.605Z" }, + { url = "https://files.pythonhosted.org/packages/94/16/24d18851334be09c25e87f74307c84950f18c324a4d3c0b41dabdbf19c29/ormsgpack-1.12.2-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:bc68dd5915f4acf66ff2010ee47c8906dc1cf07399b16f4089f8c71733f6e36c", size = 378717, upload-time = "2026-01-18T20:55:26.164Z" }, + { url = "https://files.pythonhosted.org/packages/b5/a2/88b9b56f83adae8032ac6a6fa7f080c65b3baf9b6b64fd3d37bd202991d4/ormsgpack-1.12.2-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46d084427b4132553940070ad95107266656cb646ea9da4975f85cb1a6676553", size = 203183, upload-time = "2026-01-18T20:55:18.815Z" }, + { url = "https://files.pythonhosted.org/packages/a9/80/43e4555963bf602e5bdc79cbc8debd8b6d5456c00d2504df9775e74b450b/ormsgpack-1.12.2-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c010da16235806cf1d7bc4c96bf286bfa91c686853395a299b3ddb49499a3e13", size = 210814, upload-time = "2026-01-18T20:55:33.973Z" }, + { url = "https://files.pythonhosted.org/packages/78/e1/7cfbf28de8bca6efe7e525b329c31277d1b64ce08dcba723971c241a9d60/ormsgpack-1.12.2-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18867233df592c997154ff942a6503df274b5ac1765215bceba7a231bea2745d", size = 212634, upload-time = "2026-01-18T20:55:28.634Z" }, + { url = "https://files.pythonhosted.org/packages/95/f8/30ae5716e88d792a4e879debee195653c26ddd3964c968594ddef0a3cc7e/ormsgpack-1.12.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b009049086ddc6b8f80c76b3955df1aa22a5fbd7673c525cd63bf91f23122ede", size = 387139, upload-time = "2026-01-18T20:56:02.013Z" }, + { url = "https://files.pythonhosted.org/packages/dc/81/aee5b18a3e3a0e52f718b37ab4b8af6fae0d9d6a65103036a90c2a8ffb5d/ormsgpack-1.12.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:1dcc17d92b6390d4f18f937cf0b99054824a7815818012ddca925d6e01c2e49e", size = 482578, upload-time = "2026-01-18T20:55:35.117Z" }, + { url = "https://files.pythonhosted.org/packages/bd/17/71c9ba472d5d45f7546317f467a5fc941929cd68fb32796ca3d13dcbaec2/ormsgpack-1.12.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f04b5e896d510b07c0ad733d7fce2d44b260c5e6c402d272128f8941984e4285", size = 425539, upload-time = "2026-01-18T20:56:04.009Z" }, + { url = "https://files.pythonhosted.org/packages/2e/a6/ac99cd7fe77e822fed5250ff4b86fa66dd4238937dd178d2299f10b69816/ormsgpack-1.12.2-cp314-cp314-win_amd64.whl", hash = "sha256:ae3aba7eed4ca7cb79fd3436eddd29140f17ea254b91604aa1eb19bfcedb990f", size = 117493, upload-time = "2026-01-18T20:56:07.343Z" }, + { url = "https://files.pythonhosted.org/packages/3a/67/339872846a1ae4592535385a1c1f93614138566d7af094200c9c3b45d1e5/ormsgpack-1.12.2-cp314-cp314-win_arm64.whl", hash = "sha256:118576ea6006893aea811b17429bfc561b4778fad393f5f538c84af70b01260c", size = 111579, upload-time = "2026-01-18T20:55:21.161Z" }, + { url = "https://files.pythonhosted.org/packages/49/c2/6feb972dc87285ad381749d3882d8aecbde9f6ecf908dd717d33d66df095/ormsgpack-1.12.2-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7121b3d355d3858781dc40dafe25a32ff8a8242b9d80c692fd548a4b1f7fd3c8", size = 378721, upload-time = "2026-01-18T20:55:52.12Z" }, + { url = "https://files.pythonhosted.org/packages/a3/9a/900a6b9b413e0f8a471cf07830f9cf65939af039a362204b36bd5b581d8b/ormsgpack-1.12.2-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ee766d2e78251b7a63daf1cddfac36a73562d3ddef68cacfb41b2af64698033", size = 203170, upload-time = "2026-01-18T20:55:44.469Z" }, + { url = "https://files.pythonhosted.org/packages/87/4c/27a95466354606b256f24fad464d7c97ab62bce6cc529dd4673e1179b8fb/ormsgpack-1.12.2-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:292410a7d23de9b40444636b9b8f1e4e4b814af7f1ef476e44887e52a123f09d", size = 212816, upload-time = "2026-01-18T20:55:23.501Z" }, + { url = "https://files.pythonhosted.org/packages/73/cd/29cee6007bddf7a834e6cd6f536754c0535fcb939d384f0f37a38b1cddb8/ormsgpack-1.12.2-cp314-cp314t-win_amd64.whl", hash = "sha256:837dd316584485b72ef451d08dd3e96c4a11d12e4963aedb40e08f89685d8ec2", size = 117232, upload-time = "2026-01-18T20:55:45.448Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "psycopg" +version = "3.3.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/db/2f/cb91e5502ec9de1de6f1b76cfbf69531932725361168bb06963620c77e2e/psycopg-3.3.4.tar.gz", hash = "sha256:e21207764952cff81b6b8bdacad9a3939f2793367fdac2987b3aac36a651b5bc", size = 165799, upload-time = "2026-05-01T23:31:55.179Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/e0/7b3dee031daae7743609ce3c746565d4a3ed7c2c186479eb48e34e838c64/psycopg-3.3.4-py3-none-any.whl", hash = "sha256:b6bbc25ccf05c8fad3b061d9db2ef0909a555171b84b07f29458a447253d679a", size = 213001, upload-time = "2026-05-01T23:20:50.816Z" }, +] + +[package.optional-dependencies] +binary = [ + { name = "psycopg-binary", marker = "implementation_name != 'pypy'" }, +] + +[[package]] +name = "psycopg-binary" +version = "3.3.4" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/7d/03818e13ba7f36de93573c93ee3482006d3dfa8b0f8d28df511bad0a1a92/psycopg_binary-3.3.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5ab28a2a7649df3b72e6b674b4c190e448e8e77cf496a65bd846472048de2089", size = 4591122, upload-time = "2026-05-01T23:27:56.162Z" }, + { url = "https://files.pythonhosted.org/packages/a5/b9/11b341edf8d54e2694726b273fe9652b254d989f4f63e3ac6816ad6b55f4/psycopg_binary-3.3.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6402a9d8146cf4b3974ded3fd28a971e83dc6a0333eb7822524a3aa20b546578", size = 4669943, upload-time = "2026-05-01T23:28:04.522Z" }, + { url = "https://files.pythonhosted.org/packages/8b/18/4665bacd65e7865b4372fcd8abb8b9186ada4b0025f8c2ca691b364a556c/psycopg_binary-3.3.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:580ae30a5f95ccd90008ec697d3ed6a4a2047a516407ad904283fa42086936e9", size = 5469697, upload-time = "2026-05-01T23:28:11.337Z" }, + { url = "https://files.pythonhosted.org/packages/7c/b1/b83136c6e510593d9b0c759ba5384337bc4ad82d19fda675adc4b2703c84/psycopg_binary-3.3.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e7510c37550f91a187e3660a8cc50d4b760f8c3b8b2f89ebc5698cd2c7f2c85d", size = 5152995, upload-time = "2026-05-01T23:28:20.529Z" }, + { url = "https://files.pythonhosted.org/packages/67/8d/a9821e2a648afe6091989929982a3b0f00b2631a859cb81379728f08fb75/psycopg_binary-3.3.4-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77df19583501ea288eaf15ac0fe7ad01e6d8091a91d5c41df5c718f307d8e31b", size = 6738180, upload-time = "2026-05-01T23:28:30.654Z" }, + { url = "https://files.pythonhosted.org/packages/7e/58/2e349e8d23905dc2317b80ac65f48fb6f821a4777a4e994a60da91c4850f/psycopg_binary-3.3.4-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:018fbed325936da502feb546642c982dcc4b9ffdea32dfef78dbf3b7f7ad4070", size = 4978828, upload-time = "2026-05-01T23:28:37.277Z" }, + { url = "https://files.pythonhosted.org/packages/45/48/57b00d03b4721878326122a1f1e6b0a90b85bcaec56b5b2f8ea6cfa45235/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:17a21953a9e5ff3a16dab692625a3676e2f101db5e40072f39dbee2250194d68", size = 4509757, upload-time = "2026-05-01T23:28:43.078Z" }, + { url = "https://files.pythonhosted.org/packages/25/37/33b47d8c007df69aec500df5889767c4d313748e8e9e27a2fef8a6dabcee/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:eb05ee1c2b817d27c537333224c9e83c7afb86fe7296ba970990068baf819b16", size = 4190546, upload-time = "2026-05-01T23:28:50.016Z" }, + { url = "https://files.pythonhosted.org/packages/ca/c6/32b0835dbc2122617902b649d76a91c1e75406e76bf3d595b0c3bb5ffad6/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:773d573e11f437ce0bdb95b7c18dc58390494f96d43f8b45b9760436114f7652", size = 3926197, upload-time = "2026-05-01T23:28:55.55Z" }, + { url = "https://files.pythonhosted.org/packages/cd/68/d190ef0c0c5b16ded07831dabc8ddd412f4cdab07ec6e30ed38d9bda0e1f/psycopg_binary-3.3.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:71e55ccbdfae79a2ed9c6369c3008a3025817ff9d7e27b32a2d84e2a4267e66e", size = 4236627, upload-time = "2026-05-01T23:29:05.336Z" }, + { url = "https://files.pythonhosted.org/packages/25/8f/81dcbc2e8454b74d14881275ea45f00791052dac531a9fa8be1730d1685b/psycopg_binary-3.3.4-cp312-cp312-win_amd64.whl", hash = "sha256:494ca54901be8cf9eb7e02c25b731f2317c378efa44f43e8f9bd0e1184ae7be4", size = 3560782, upload-time = "2026-05-01T23:29:11.967Z" }, + { url = "https://files.pythonhosted.org/packages/09/43/13e9c406fbbf354580476e248a16b64802a376873ebe6339e30bb655572d/psycopg_binary-3.3.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fbd1d4ed566895ad2d3bf4ddfd8bae90026930ddf29df3b9d91d32c8c47866a7", size = 4590377, upload-time = "2026-05-01T23:29:18.782Z" }, + { url = "https://files.pythonhosted.org/packages/22/be/2923cd7c3683e7afdecf4f10796a18de02f5c5ddc0969aa2ad0a8cdd3bbd/psycopg_binary-3.3.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:75a9067e236f9b9ae3535b66fe99bddb33d39c0de10112e49b9ab11eee53dc31", size = 4669023, upload-time = "2026-05-01T23:29:25.884Z" }, + { url = "https://files.pythonhosted.org/packages/96/a0/2c913d6fe13d6a8bd13597d36739bf47af063ad9399e402cfecab16f3c1e/psycopg_binary-3.3.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:b56b603ebcea8aa10b46228b8410ba7f13e7c2ee54389d4d9be0927fd8ce2a70", size = 5467423, upload-time = "2026-05-01T23:29:33.416Z" }, + { url = "https://files.pythonhosted.org/packages/e7/38/205d10bc1ad0df4a21c5c51659126bd3ea0ef98fcad1e852f78c249bb9c3/psycopg_binary-3.3.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c677c4ad433cb7150c8cd304a0769ae3bcfbe5ea0676eb53faa7b1443b16d0d3", size = 5151137, upload-time = "2026-05-01T23:29:42.013Z" }, + { url = "https://files.pythonhosted.org/packages/36/fc/f0381ddcd45eff3bb70dbca6823a996048d7f507b2ec3fc92c6fabc0fe87/psycopg_binary-3.3.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:26df2717e59c0473e4465a97dfb1b7afebaa479277870fd5784d1436470db47c", size = 6736671, upload-time = "2026-05-01T23:29:51.626Z" }, + { url = "https://files.pythonhosted.org/packages/95/40/fa545ae152c24327651e5624e4902121e808270be36c10b12e9939be09bc/psycopg_binary-3.3.4-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1dc1f79fd16bb1f3f4421417a514607539f17804d95c7ed617265369d1981cae", size = 4979601, upload-time = "2026-05-01T23:29:56.961Z" }, + { url = "https://files.pythonhosted.org/packages/86/e4/2f8a47ee97f90cd2b933d0463081d35631ff419de2b8c984a5f369857de0/psycopg_binary-3.3.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:136f199a407b5348b9b857c504aff60c77622a28482e7195839ce1b51238c4cc", size = 4510513, upload-time = "2026-05-01T23:30:07.243Z" }, + { url = "https://files.pythonhosted.org/packages/0e/0e/94e842ff4a7f98ed162580ca2e8b8864b28c1e0350f2443f8ee47f821167/psycopg_binary-3.3.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b6f5a29e9c775b9f12a1a717aa7a2c80f9e1db6f27ba44a5b59c80ac61d2ffcf", size = 4187243, upload-time = "2026-05-01T23:30:15.352Z" }, + { url = "https://files.pythonhosted.org/packages/d0/83/fc6c174b672e29b7de996ea77b6cbddf46c891751c3355f6974292baa6b4/psycopg_binary-3.3.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:ee17a2cf4943cde261adfad1bbc5bf38d6b3776d7afff74c7cabcbeaeb08c260", size = 3927347, upload-time = "2026-05-01T23:30:21.186Z" }, + { url = "https://files.pythonhosted.org/packages/e9/65/768364d4a97a15b1a7f47ba52688c1686f22941d8332a8398cefc468e25f/psycopg_binary-3.3.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5c4ab71be17bdca30cb34c34c4e1496e2f5d6f20c199c12bad226070b22ef9bf", size = 4236393, upload-time = "2026-05-01T23:30:26.211Z" }, + { url = "https://files.pythonhosted.org/packages/bd/3b/218efbc9e645becd80cdf651acda05f85cfe546b7a9c0458c7cbc8fe1f74/psycopg_binary-3.3.4-cp313-cp313-win_amd64.whl", hash = "sha256:dbfdb9b6cc79f31104a7b162a2b921b765fcc62af6c00540a167a8de47e4ed38", size = 3564592, upload-time = "2026-05-01T23:30:31.764Z" }, + { url = "https://files.pythonhosted.org/packages/48/a6/828c9185701dab71b234c2a76c38a08b098ebfec5020716b4e93807492b5/psycopg_binary-3.3.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:28b7398fdd19db3232c884fb24550bdfe951221f510e195e233299e4c9b78f97", size = 4607292, upload-time = "2026-05-01T23:30:38.962Z" }, + { url = "https://files.pythonhosted.org/packages/92/58/5b40dbc9d839045c9dae956960e4fb6d20bcabe6c59a2aa34fc3a371913f/psycopg_binary-3.3.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1fbaa292a3c8bb61b45df1ad3da1908ccee7cb889db9425e3557d9e34e2a4829", size = 4687023, upload-time = "2026-05-01T23:30:47.227Z" }, + { url = "https://files.pythonhosted.org/packages/85/a9/793f0ac107a9003b48441d0d1f9f616d96e0f37458dd8dc12528ceff55fb/psycopg_binary-3.3.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:94596f9e7633ee3f6440711d43bb70aa31cc0a46a900ab8b4201a366ace5c9e7", size = 5486985, upload-time = "2026-05-01T23:30:55.517Z" }, + { url = "https://files.pythonhosted.org/packages/8f/26/42e8533497e2592334f68ec529cf5f840f7fa4e99575a4bb61aa184dbfbf/psycopg_binary-3.3.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8c0056529e68dbe9184cd4019a1f3d8f3a4ead2f6fc7a5afcf27d3314edd1277", size = 5168745, upload-time = "2026-05-01T23:31:01.904Z" }, + { url = "https://files.pythonhosted.org/packages/15/af/b7151776cc08d5935d45c833ec818a9beb417cf7c08239af1aafbdae78ee/psycopg_binary-3.3.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c09aad7051326e7603c14e50636db9c01f78272dc54b3accff03d46370461e6", size = 6761486, upload-time = "2026-05-01T23:31:14.511Z" }, + { url = "https://files.pythonhosted.org/packages/d0/ed/c92533b9124712d592cbf1cd6c76da933a2e0acea81dfe1fbe7e735f0cff/psycopg_binary-3.3.4-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:514404ed543efd620c85602b747df2a23cf1241b4067199e1a66f2d2757aaa41", size = 4997427, upload-time = "2026-05-01T23:31:20.901Z" }, + { url = "https://files.pythonhosted.org/packages/a2/23/ccadfd0de416aa188356daa199453af24087b042e296088706d190ae0295/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:46893c26858be12cc49ca4226ed6a60b4bfccadd946b3bebb783a60b38788228", size = 4533549, upload-time = "2026-05-01T23:31:26.204Z" }, + { url = "https://files.pythonhosted.org/packages/fd/a0/c8f43cee36386f7bc891ab41a9d31ea07cf9826038e732da79f26b1e5f34/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:df1d567fc430f6df15c9fcf67d87685fc49bdb325adc0db5af1adfb2f44eb5c9", size = 4210256, upload-time = "2026-05-01T23:31:33.884Z" }, + { url = "https://files.pythonhosted.org/packages/4e/2c/c1547871be3790676e8868b38655496422f94f0978dfb66b74bdba2f1676/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:6b9016b1714da4dd5ecaaa75b82098aa5a0b87854ce9b092e21c27c4ae23e014", size = 3946204, upload-time = "2026-05-01T23:31:39.626Z" }, + { url = "https://files.pythonhosted.org/packages/c4/b1/f6670f00fa7ea601584623f6c11602ab92117d83eaff885e0210f6de7418/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:47c656a8a7ba6eb0cff1801a4caaa9c8bdc12d03080e273aff1c8ac39971a77e", size = 4255811, upload-time = "2026-05-01T23:31:44.986Z" }, + { url = "https://files.pythonhosted.org/packages/eb/e6/5fff07a70d1f945ed90ae131c3bd76cab32beff7c58c6db15ad5820b6d1f/psycopg_binary-3.3.4-cp314-cp314-win_amd64.whl", hash = "sha256:c37e024c07308cd06cf3ec51bfd0e7f6157585a4d84d1bce4a7f5f7913719bf8", size = 3666849, upload-time = "2026-05-01T23:31:51.165Z" }, +] + +[[package]] +name = "pyarrow" +version = "25.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3d/e3/27f57f80141379d60defe6703eb50a707325706f07fedfd1312c7a751995/pyarrow-25.0.1.tar.gz", hash = "sha256:9150a83248bfed9813ea3c3af74c3856c1984d444aa28e58bf7733b9750ddf6a", size = 1201653, upload-time = "2026-08-10T12:40:53.904Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/e2/9ab15b88cbfac28e16419ce5439ec29234c5172cb8259301b4ba639bdec0/pyarrow-25.0.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:df961f2e7ae9cf496459259d798652c70625f6c080650d6952f8c04053c58ee9", size = 35861559, upload-time = "2026-08-10T12:38:02.567Z" }, + { url = "https://files.pythonhosted.org/packages/58/79/a0036dbe1eabe1f73127427342f1d99982584c4a2cde2651d6c93499c6f6/pyarrow-25.0.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:cc4aa407fde9fc660be3939e49ea31f50f3e9fec17c0ec63159f7711edd3efc9", size = 37628383, upload-time = "2026-08-10T12:38:09.083Z" }, + { url = "https://files.pythonhosted.org/packages/13/49/d93a57d375f4bf0cf82913dd6bb54acafde83dd993be2282c81ac5616cad/pyarrow-25.0.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:4340f0ba6c1d2e13f21658de1d7c662ca2545018568d0030a1e9afca159d87e3", size = 46820190, upload-time = "2026-08-10T12:38:15.458Z" }, + { url = "https://files.pythonhosted.org/packages/60/c9/711ca85d79f1ec98f29a5eae2b051e25b4ecec5de3e3c0e2d5c5dcb15664/pyarrow-25.0.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:5389cdf79447ed1515c9e31620e6e1e2302249564d603f2ad727d4f6d313e4c3", size = 50102437, upload-time = "2026-08-10T12:38:22.487Z" }, + { url = "https://files.pythonhosted.org/packages/80/53/8fb8359ff17cfb6263a1cf3ebf7caec9fe197de118719e84fcb1d0618026/pyarrow-25.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d51592cb7561e87877c506113e7adbf1342ab579e6c21f0ef44b8ba41cb74c80", size = 49942424, upload-time = "2026-08-10T12:38:28.755Z" }, + { url = "https://files.pythonhosted.org/packages/e8/83/4e5ae02a9341571b18a6fca380ac7a58ce6ddae7ab3c060208c0a1e79f02/pyarrow-25.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6109c94d8b9f3b17a041daca16cacb2f651ad8f1ef70a4232c2c0f37a23da2a8", size = 53144206, upload-time = "2026-08-10T12:38:34.862Z" }, + { url = "https://files.pythonhosted.org/packages/65/ee/197cbf47e49f83e6ebeb946a5259a48a638dea27ac774db42fe78022179d/pyarrow-25.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:8858d7bfc22e3f51529aeaa4077225029724623e4595dc9eff8c793935c34140", size = 27953934, upload-time = "2026-08-10T12:38:39.808Z" }, + { url = "https://files.pythonhosted.org/packages/cc/8d/8f271a7a034c834910ec925d56fa4b29733b1380f5289419f5aaa3b02777/pyarrow-25.0.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:c7c534ec03c358a76ea3e505e74c1b6aef290af90c444dfd092dbfe23e755b85", size = 35855328, upload-time = "2026-08-10T12:38:45.489Z" }, + { url = "https://files.pythonhosted.org/packages/d2/cd/5bac242f4e841b9971d5eb94fdfe2577e2b70be983e27401e72055786037/pyarrow-25.0.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:dda9470024204d7bbf2042b47c6e8a0e47a3eeb8e34405882dfaea6577e0c153", size = 37622415, upload-time = "2026-08-10T12:38:51.107Z" }, + { url = "https://files.pythonhosted.org/packages/63/1f/96d03b4e1506524f7087adb0fd6b2f69f0c9c7aaff1ec36d8030082e15a5/pyarrow-25.0.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:44a9120ce5bd81936b8ab9a88076e3fd47c2c6838e0e43630fed83626aca81d9", size = 46813813, upload-time = "2026-08-10T12:38:57.773Z" }, + { url = "https://files.pythonhosted.org/packages/98/d6/33a411115b61dbfc16ad6ad73e71730f6fea654ee3667673bc53ab0e2fe7/pyarrow-25.0.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:0befcf816e45a1af33ac775a9970b749e4868a230c7372f0ae5e932bee27039f", size = 50104452, upload-time = "2026-08-10T12:39:04.579Z" }, + { url = "https://files.pythonhosted.org/packages/33/ae/b1b97c9ca87f9f9ddbb5230c798df94eccce61bd79b9b45458c69a478588/pyarrow-25.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3f89685964f46e4216103c75483aac0c0692a5f72212d7ca835adba5ede56ce3", size = 49951343, upload-time = "2026-08-10T12:39:11.8Z" }, + { url = "https://files.pythonhosted.org/packages/98/9e/a112df5cfd5a68cb1d9fc31cfe38c28d5aec9f10865ce37ecef2e4450873/pyarrow-25.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6943e2fe7954d29d84de45d29d34c8dc36ce96570e67d89aa9976e650a4a9138", size = 53144784, upload-time = "2026-08-10T12:39:20.503Z" }, + { url = "https://files.pythonhosted.org/packages/31/24/97e8bd98f1e3b07e2ba08bcdff690674fbe16d69a7d2712cc3884665e615/pyarrow-25.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:31e49a7888fcdf3a835da33ae777f6bb9a866334e5a789282fc26dcf426f7f15", size = 27870159, upload-time = "2026-08-10T12:39:26.161Z" }, + { url = "https://files.pythonhosted.org/packages/36/4c/b525824ad3094076919273cd97db61fb3d78252dee76fa3b8dc8f76774aa/pyarrow-25.0.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:bf0b672390cdcb640d7288f96b826d71ff4e9abb254a86c89890baf51a29cee6", size = 35885255, upload-time = "2026-08-10T12:39:32.366Z" }, + { url = "https://files.pythonhosted.org/packages/08/62/448bb0e940de41aec31d1a956e63ad9c54afdf122a103cc3ab20c2a3ce33/pyarrow-25.0.1-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:38a9a4b4b9613380e200641891495a56c3d5a98a092db4a870af9975e220471d", size = 37644461, upload-time = "2026-08-10T12:39:38.142Z" }, + { url = "https://files.pythonhosted.org/packages/6e/9a/13587e38bd4806fd218f50fd13b8903fab60588a699ff0c406372e5b4043/pyarrow-25.0.1-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:0b726ad7e7b669be982b0c71c07fe4b037d654354130da79a7902a669e93a66b", size = 46877146, upload-time = "2026-08-10T12:39:43.722Z" }, + { url = "https://files.pythonhosted.org/packages/8d/61/1c5d1229fa21da4cff5365e41e57177aaac57c563c727f35419b8513d1c1/pyarrow-25.0.1-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:9171748cdf796972d85a4b60157c279913e242992e350c90c7450182a9838b2a", size = 50131616, upload-time = "2026-08-10T12:39:49.304Z" }, + { url = "https://files.pythonhosted.org/packages/43/20/291e1d65cc0b09aa19f03cf25cf51a2f5fa94b5db315178f2d254ed5cad4/pyarrow-25.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b7a296aac7a71fa0886c08e155ddb6c636a50013f801f6178daafa0f9e726188", size = 50008879, upload-time = "2026-08-10T12:39:56.891Z" }, + { url = "https://files.pythonhosted.org/packages/8b/7c/1b7c9ec28e76576337e4f97b31141c9a181b89b6d1d6221e9d8205621a58/pyarrow-25.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:0fe7c8b6c03969b49c8c66182e4a18e3819ab92d07cfab5d8370c531b9369ef0", size = 53170864, upload-time = "2026-08-10T12:40:04.918Z" }, + { url = "https://files.pythonhosted.org/packages/b7/75/f3d789dc06011a765d14d86bda799cf72ac1d715b6a6edecaa0d73d95062/pyarrow-25.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:f729cfdbd36fd99d543b67a914d2de044c84ebe45be8b34902b299b608c15c8f", size = 28620729, upload-time = "2026-08-10T12:40:51.41Z" }, + { url = "https://files.pythonhosted.org/packages/fc/05/647a8ee6f7c2662feb6921315617bc04dcd6034763fb61b1199720bf6162/pyarrow-25.0.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:59a2de54c0cbd954da861eee4d1d330f8e909c45b53455baef696380f2c55033", size = 36130288, upload-time = "2026-08-10T12:40:11.014Z" }, + { url = "https://files.pythonhosted.org/packages/93/f8/c9ee997554d7bea94520667dd1933f109ac1da3ee3556d2b49381e023484/pyarrow-25.0.1-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:35935cd5de130aa5cf4dea052a63e6bf2e17006c35c3a468194242b9b2bf5956", size = 37762187, upload-time = "2026-08-10T12:40:16.592Z" }, + { url = "https://files.pythonhosted.org/packages/a2/08/a28c01c7fe9e96e8233ce2d13df1d402f4f999f848f51d2daacd6bb4c036/pyarrow-25.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:f3831aaa25c67a99f99dc8b05873cb9d64560390372e2aa197ce9dd4a3f06a44", size = 46888003, upload-time = "2026-08-10T12:40:23.242Z" }, + { url = "https://files.pythonhosted.org/packages/1b/b9/58612e977d28dc58c878448866838369ee8da2f1e7cc8ed2c84b952aafee/pyarrow-25.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:6a1fdfc6659b6b19022f2e50627fb5cf7156a66c46bf4299379955cbe742382a", size = 50079036, upload-time = "2026-08-10T12:40:29.169Z" }, + { url = "https://files.pythonhosted.org/packages/72/13/66e1402dcc860e1dc2760b1e0292c9a569b62b3bccab69def1b3e907d006/pyarrow-25.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:169d3429d5be7c752125890620f75a60776d38b0035eddae939651640822332e", size = 50040226, upload-time = "2026-08-10T12:40:35.186Z" }, + { url = "https://files.pythonhosted.org/packages/78/10/3f1a5497a7ef732ab0f03ecca3e66d89d9c0f57fdc61b4794c456b781f01/pyarrow-25.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:119297a6dc197e45d9c6d4415f7814a67ffa36c180d26f68c154c58067ae782d", size = 53149035, upload-time = "2026-08-10T12:40:41.454Z" }, + { url = "https://files.pythonhosted.org/packages/93/c0/37d4a7e8e2f7a6076283673d5298018ca26478b934c6ee369e10505ab32c/pyarrow-25.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:4288f27577352d608ca08553b0865e4a9b3aa14820c5d95b53337218d609835b", size = 28753071, upload-time = "2026-08-10T12:40:46.623Z" }, +] + +[[package]] +name = "pydantic" +version = "2.13.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" }, +] + +[[package]] +name = "pydantic-core" +version = "2.46.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" }, + { url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" }, + { url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" }, + { url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" }, + { url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" }, + { url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" }, + { url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" }, + { url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" }, + { url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" }, + { url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" }, + { url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" }, + { url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" }, + { url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" }, + { url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" }, + { url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" }, + { url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" }, + { url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" }, + { url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" }, + { url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" }, + { url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" }, + { url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" }, + { url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" }, + { url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" }, + { url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" }, + { url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" }, + { url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" }, + { url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" }, + { url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" }, + { url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" }, + { url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" }, + { url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" }, + { url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" }, + { url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" }, + { url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" }, + { url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" }, + { url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" }, + { url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" }, + { url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" }, + { url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" }, + { url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" }, + { url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" }, + { url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" }, + { url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" }, + { url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" }, + { url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" }, + { url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" }, + { url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" }, + { url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" }, + { url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" }, + { url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" }, + { url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" }, + { url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" }, + { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" }, + { url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" }, + { url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" }, +] + +[[package]] +name = "pygments" +version = "2.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/49/2e/ced460408999b33da6b31b0021b0f37d329e202d4169aeb164493778f25b/pygments-2.21.0.tar.gz", hash = "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c", size = 5005329, upload-time = "2026-08-17T08:02:48.824Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/46/17f022dd3e953bf20a04a028a21ec746d942f8d2af30fa0f124fa0e6a684/pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9", size = 1250147, upload-time = "2026-08-17T08:02:44.912Z" }, +] + +[[package]] +name = "pytest" +version = "8.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" }, +] + +[[package]] +name = "pytest-django" +version = "4.14.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/44/f6/3851312120c2bf2f19cafff931e75059aad1ba670703cd751e2fde9bc942/pytest_django-4.14.0.tar.gz", hash = "sha256:26787dd3f422cfbab8f55b80a776e2edea7a11092cb74e960bef1312515708ef", size = 94700, upload-time = "2026-08-10T14:13:08.319Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9c/03/850bffad2b581c440ca51c039d74504d5a422c94bda0bdb8a8ba5068d48b/pytest_django-4.14.0-py3-none-any.whl", hash = "sha256:c533b08d89cc675efcd5398eea270b34547e35f9a3608e2c9748dd88428ea187", size = 27067, upload-time = "2026-08-10T14:13:06.998Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "requests" +version = "2.34.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, +] + +[[package]] +name = "requests-toolbelt" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", size = 206888, upload-time = "2023-05-01T04:11:33.229Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" }, +] + +[[package]] +name = "ruff" +version = "0.16.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/61/b3/3213589383f8f1b3938781bd1278713f6d18621a14992b3e81fefb8a5ef9/ruff-0.16.3.tar.gz", hash = "sha256:e76d33a347661a84b5be6d043d0347fdc745dfdcf825a8f4fed64b5e26eebdf2", size = 4891904, upload-time = "2026-08-13T15:17:13.381Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/96/493770daebd68c0a67f1549fdf519f53be51fc435186c0585bcc272fd76c/ruff-0.16.3-py3-none-linux_armv6l.whl", hash = "sha256:0c5710e247a58a4521e66e124ba9a74655b414f61ba3a2e9e3811e11098f48f7", size = 10902799, upload-time = "2026-08-13T15:16:27.382Z" }, + { url = "https://files.pythonhosted.org/packages/5e/e6/2becf3942fddc29a29b8df47691d456fb1085391a694f74d84513251418c/ruff-0.16.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fe155130631a2471fd2e14a7a664a4dfbd7194b8229c3d7b2a40b21178639081", size = 11135539, upload-time = "2026-08-13T15:16:30.87Z" }, + { url = "https://files.pythonhosted.org/packages/3e/1e/4b8b72f0d006dbf19326aa99f9ca0ee2ff374187c4d301cf529a51aa06fe/ruff-0.16.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e2ed719e14aa64d895c2ee922594a90a43c861a93f0575a95ff8c47cdbd13eb9", size = 10475095, upload-time = "2026-08-13T15:16:33.259Z" }, + { url = "https://files.pythonhosted.org/packages/92/32/2201fa49ba1f6c101ee321e83f051ac7a4b8d07b0ef6b4d3f2772b302275/ruff-0.16.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e0b1da805eb043654645d74d5de1e5ce2edc686e40790d2b86f56d71cc06a84", size = 10668771, upload-time = "2026-08-13T15:16:35.65Z" }, + { url = "https://files.pythonhosted.org/packages/c3/66/4afc5c8363bd04d45effce1b7c8713ca037d7a6740b7451a2403a6e3a972/ruff-0.16.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a37bdea0bbe21780f590bf437d6412c8c4e1b6cd010f91a65c2c40c5e5f5f870", size = 10699568, upload-time = "2026-08-13T15:16:38.195Z" }, + { url = "https://files.pythonhosted.org/packages/53/fd/c67d246bf36bf1698551c56de39e95cd07f70e64433e0098e6267d77061b/ruff-0.16.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09571e6d1288ed9be475207a3ac04ada404f1cd898104be0f6ab8d7df438575b", size = 11499365, upload-time = "2026-08-13T15:16:40.623Z" }, + { url = "https://files.pythonhosted.org/packages/67/0b/00ecbceb99a263af7b12f6f05ac3c92bc47b905e91adc3f207a836e3bc01/ruff-0.16.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c18c5a101eb540010638cc1ff3c84944d3adb3df62b8d98ca8f22ba484d3413", size = 12311728, upload-time = "2026-08-13T15:16:43.564Z" }, + { url = "https://files.pythonhosted.org/packages/54/b2/b7b3bb54f4d3f7db504e476ad4ab8de530dceebe2c061384b2757ee419e8/ruff-0.16.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8457c44f15033c85ddbb77b15d451df9e24e4bd03b628396dd3610cedc3b8f82", size = 11699896, upload-time = "2026-08-13T15:16:46.209Z" }, + { url = "https://files.pythonhosted.org/packages/c7/30/4c468429ac195addc5ee1b717b6ab1b66632786737ca3b2ed3443fb0c26a/ruff-0.16.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:294b95c4ae0cda9388525c2047778aa758d6b8d4bb876fd4e9eaa3ebc92343eb", size = 11058736, upload-time = "2026-08-13T15:16:48.823Z" }, + { url = "https://files.pythonhosted.org/packages/43/67/7a113cdaddf24b64d7f75b1242a99d04c82fcef4f6921fdbb832beaffb5f/ruff-0.16.3-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:3d0c7c40c87c2a820509c31ba007968da6e1306468c067b2d82fbfdbcd0e8474", size = 11586911, upload-time = "2026-08-13T15:16:51.913Z" }, + { url = "https://files.pythonhosted.org/packages/f1/c1/2e66f24c0f3ead25a5e660111778685e505e5da353c82802bf49f0cbe7b9/ruff-0.16.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:9f738c0fdfa8eed0b2ce7fb27ee7258208a92a68d7949e62aa15164bc7b389da", size = 10954265, upload-time = "2026-08-13T15:16:54.763Z" }, + { url = "https://files.pythonhosted.org/packages/c2/ba/4cee23bf52cba9a058d3726de623624daf50ef9638868edd86f4126157f6/ruff-0.16.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fb785f0be25abe69d320415cd4f833b59e17ba7613d9ba6a958023b6bceb0a50", size = 10709886, upload-time = "2026-08-13T15:16:57.339Z" }, + { url = "https://files.pythonhosted.org/packages/82/df/7da7194fa5d9dc0a285f7e6fa5a4722e7c63faac0b45b614ded9314363a1/ruff-0.16.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c5536e3acfbf9563085aa2be7b13c629c3077e902afc5b941ac44024dbb9f506", size = 11210392, upload-time = "2026-08-13T15:17:00.171Z" }, + { url = "https://files.pythonhosted.org/packages/35/85/7795f6e817af050e7517bf3e7aa9b061cce70ef33d280aad902c956c1ecf/ruff-0.16.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a2d85c02f9b8e165d85e6779184d38c4132de12603dab59c51c28e22584f9e4d", size = 11626910, upload-time = "2026-08-13T15:17:03.299Z" }, + { url = "https://files.pythonhosted.org/packages/78/9b/475b927cf27a5cbbda3c7bafb69ed6ff77e1d7923d5d85f17c2749d7ae32/ruff-0.16.3-py3-none-win32.whl", hash = "sha256:388cdf2166642bd9b13d52b5932d3170f34f8abed7e8d9a855f1d84b83645a0a", size = 10931415, upload-time = "2026-08-13T15:17:05.726Z" }, + { url = "https://files.pythonhosted.org/packages/b2/99/e2a2bfc4fbf0a1e8a916bc9ebe6fe6c58cc34c28e0ffc6ce281d572d1c2e/ruff-0.16.3-py3-none-win_amd64.whl", hash = "sha256:e80a7d69ca2a6d1c4d352ec91458cdca6e56c83cdbcabd93e4abe1e53591d948", size = 11445993, upload-time = "2026-08-13T15:17:08.353Z" }, + { url = "https://files.pythonhosted.org/packages/69/3e/4132e539aed78c148854d4997a2685b0ed4dc4e87110b59ce528564e184e/ruff-0.16.3-py3-none-win_arm64.whl", hash = "sha256:b8ca152da82c1acc1fa8d5874b15951935f0eef46f10e6954c83859011b6178a", size = 11399302, upload-time = "2026-08-13T15:17:10.908Z" }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, +] + +[[package]] +name = "sqlparse" +version = "0.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5f/d3/3f06a1006f2261d1342aefb3c71eed02f5d4ca5bdbecd86ebc12ad38306e/sqlparse-0.6.0.tar.gz", hash = "sha256:113c35c75365ab9cc9c7231d68c6428fb11c085fc8e9eb1ad659b7ddbf6cd2b9", size = 178477, upload-time = "2026-08-13T19:16:06.396Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/50/f00935da0ec7cbf325f8dc4f772ae46fbc7b672dd62876e73f0a94adda57/sqlparse-0.6.0-py3-none-any.whl", hash = "sha256:b861c0288ce2fa56209a9a6412d2e066ac664b3873b89c26c9d8415e8e32996f", size = 50070, upload-time = "2026-08-13T19:16:04.062Z" }, +] + +[[package]] +name = "structlog" +version = "24.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/78/a3/e811a94ac3853826805253c906faa99219b79951c7d58605e89c79e65768/structlog-24.4.0.tar.gz", hash = "sha256:b27bfecede327a6d2da5fbc96bd859f114ecc398a6389d664f62085ee7ae6fc4", size = 1348634, upload-time = "2024-07-17T12:38:43.483Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/65/813fc133609ebcb1299be6a42e5aea99d6344afb35ccb43f67e7daaa3b92/structlog-24.4.0-py3-none-any.whl", hash = "sha256:597f61e80a91cc0749a9fd2a098ed76715a1c8a01f73e336b746504d1aad7610", size = 67180, upload-time = "2024-07-17T12:38:41.043Z" }, +] + +[[package]] +name = "tenacity" +version = "9.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/47/c6/ee486fd809e357697ee8a44d3d69222b344920433d3b6666ccd9b374630c/tenacity-9.1.4.tar.gz", hash = "sha256:adb31d4c263f2bd041081ab33b498309a57c77f9acf2db65aadf0898179cf93a", size = 49413, upload-time = "2026-02-07T10:45:33.841Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/c1/eb8f9debc45d3b7918a32ab756658a0904732f75e555402972246b0b8e71/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55", size = 28926, upload-time = "2026-02-07T10:45:32.24Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/26/b09b8010994eccc3c09092e6b34058f36a460eea2d4c3e8b910c695975a0/typing_inspection-0.4.4.tar.gz", hash = "sha256:547274fa6b0a561ccf549cc9524b999a578e737d015d8709d021f9d0d13bea47", size = 76928, upload-time = "2026-08-12T12:37:25.997Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/81/4add07e5172b7ac40d8ed5ff580409a7801a4fe26d529bdd915401dabfbe/typing_inspection-0.4.4-py3-none-any.whl", hash = "sha256:65b8397ba37ccbce054456aaccddfc91e6e3083c92824df348d96ca832f3f147", size = 14750, upload-time = "2026-08-12T12:37:24.648Z" }, +] + +[[package]] +name = "tzdata" +version = "2026.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/92/ff/5a28bdfd8c3ebec42564ac7d0e54ca3db65044a9314a97f9564fa7a1e926/tzdata-2026.3.tar.gz", hash = "sha256:4a1518b8993086a7982523e071643f3c0e5f213e75b21318e78bcabfff9d1415", size = 198674, upload-time = "2026-07-10T08:50:37.887Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/6d/b53b99a9f2766d095985947a5782f1702cabb129a34f7a802d7197af832f/tzdata-2026.3-py2.py3-none-any.whl", hash = "sha256:dc096730c87af6cab1b171c9d532be840741ff5d459015e7f6947bd7d7e54931", size = 348168, upload-time = "2026-07-10T08:50:36.46Z" }, +] + +[[package]] +name = "urllib3" +version = "2.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, +] + +[[package]] +name = "uuid-utils" +version = "0.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/91/63938e0e7e7876658e5e40178e7c0735b53527886fe11797a11699c55edd/uuid_utils-0.17.0.tar.gz", hash = "sha256:abb5667a36119019b3fa320c4d10c21ebccfcc87c8a739e6a0056cee7f48dde2", size = 43220, upload-time = "2026-07-09T13:49:58.433Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/80/a7e685968e3cec99d6fe2fb25d0f5726310e1bba356da68c13dfd8b7d140/uuid_utils-0.17.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:9205068badf453d2f0821fd5d340389b4679992d7ff79d4f3e5608996dd1b287", size = 556403, upload-time = "2026-07-09T13:48:27.022Z" }, + { url = "https://files.pythonhosted.org/packages/56/47/3102d93bcb7b0bfe6bede63ff8f221a7f91348e10a37f682773be27c56d9/uuid_utils-0.17.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0fcca4e838af9ac9243b3358d7c14afa4dca286a87781124c272d6c4cad9c968", size = 285608, upload-time = "2026-07-09T13:48:28.769Z" }, + { url = "https://files.pythonhosted.org/packages/55/fb/d59695f0f8db065b93c63316eaafa05a22d75a0486978a33736c52c646d5/uuid_utils-0.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f3729e839209f3457d0d8b6a35a376fdf65577a5aecaf4cc3587d3305759ba6", size = 319926, upload-time = "2026-07-09T13:48:29.965Z" }, + { url = "https://files.pythonhosted.org/packages/5a/03/62fabcd1e990e07a0e220e8d552af45bc16f107fa8e55c2014a706bb1a1e/uuid_utils-0.17.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3dac0ad0cd9a2818d1775215365a4e8c2f8ada215529dd26f3f8cceeb67a6988", size = 327172, upload-time = "2026-07-09T13:48:31.187Z" }, + { url = "https://files.pythonhosted.org/packages/d9/37/a5081391338b459e2f8d8b12581f00f8caa6317fab510e0e85c18c59e938/uuid_utils-0.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e671b2322ef09106ecb1ca0f4c398b134d5e2c1f80d7a4f3336847a3072c0e94", size = 439075, upload-time = "2026-07-09T13:48:32.295Z" }, + { url = "https://files.pythonhosted.org/packages/59/30/91795bd01e17a13661280d4899fbf38fb05e3f38e873f9aaec106ec30aa0/uuid_utils-0.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8eb3e5caca8d3a6f72ea4cce024583f989f6f2e9186f98800213fff0176e8bcc", size = 320247, upload-time = "2026-07-09T13:48:33.64Z" }, + { url = "https://files.pythonhosted.org/packages/e5/11/09102b78303e4eb62069d6d88ef9fd661dc523e8f429e1fd67eaa78a6f44/uuid_utils-0.17.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8b72c2002202038666bf647f9a790906214c7c11cd0d6efef77b7d07bef3034a", size = 344738, upload-time = "2026-07-09T13:48:34.786Z" }, + { url = "https://files.pythonhosted.org/packages/74/f9/be95bad6954b60328878c3800258f01a6accd24fd75112d13f023462d53f/uuid_utils-0.17.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4e2ac1c0b56f2c91b6f158e29ed96b1503223fe8aa6e79b1be1dc55bd8a5131c", size = 496845, upload-time = "2026-07-09T13:48:36.057Z" }, + { url = "https://files.pythonhosted.org/packages/2d/02/8a19a34e0530d987488a068a71576a236f5c8c746630b870b57f71eb24ef/uuid_utils-0.17.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6c142bd0cb4dba31c10babe00d59f7ef6460f0ef55eaa9c1a9da270684af996a", size = 603233, upload-time = "2026-07-09T13:48:37.512Z" }, + { url = "https://files.pythonhosted.org/packages/f4/a8/b1abab36ff73b0248d82179816467f6d39a2e80fd64329a895ca94f3508e/uuid_utils-0.17.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e252db239eb41c32248e096e0d170bce5896a4fd3405556362bc3dd83d912206", size = 561401, upload-time = "2026-07-09T13:48:38.977Z" }, + { url = "https://files.pythonhosted.org/packages/61/91/70e7b528b351cc03a9ca43e6116371cdde31bb12bcead7ca2ca1367366cc/uuid_utils-0.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:237722b6581bb5b4eb4cefbcbe5c6e2980a440aabe781fbe50ebf1cb71eee4cc", size = 525314, upload-time = "2026-07-09T13:48:40.599Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f6/9167e90cf9937d6558f92d022ff3024a69d938a514d9c8faa4080f73b001/uuid_utils-0.17.0-cp312-cp312-win32.whl", hash = "sha256:46a73cacdf512f473a81f65dbf84186e08cfe6e9118fa582b6c6b33a8288a30d", size = 166831, upload-time = "2026-07-09T13:48:41.862Z" }, + { url = "https://files.pythonhosted.org/packages/5c/7d/0b889654d9ee3413f810cf4685e241285f650d98a4103ac9f3c6bcc95f29/uuid_utils-0.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:e59b60a0a4cb7541480e02090d37dc2df3b72df4c2e776fff64ce3a4e3dd4637", size = 172944, upload-time = "2026-07-09T13:48:42.992Z" }, + { url = "https://files.pythonhosted.org/packages/be/35/8c6e1bf65e4d400352885dadc656ad6d0af96e89231e3f04686bc2197128/uuid_utils-0.17.0-cp312-cp312-win_arm64.whl", hash = "sha256:d561a4c5747a1e6c7fa7c49a0292e78b4e8c456332caa084fc7abad8de828652", size = 172459, upload-time = "2026-07-09T13:48:44.271Z" }, + { url = "https://files.pythonhosted.org/packages/d2/dd/614fb9912157ac0128e6050859ccf06d9f13df9a944a803e8f80f6157e38/uuid_utils-0.17.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:d11a7bc1e02da8984d32e6de9e0826c6edac00eac17de270f372bf32f9a0af63", size = 557259, upload-time = "2026-07-09T13:48:45.664Z" }, + { url = "https://files.pythonhosted.org/packages/3e/11/d072711704de3d21bec08b6c2f36a215200ca1d5e01a390ea1ac434080a0/uuid_utils-0.17.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7a49f47ac26df3e431c56b825c1bae8e6d3d591fdbb7438c227cc9845a7e3d73", size = 286271, upload-time = "2026-07-09T13:48:47.018Z" }, + { url = "https://files.pythonhosted.org/packages/18/6d/8a63e5eb2d5a6ba69a6c2036e305075bd6f5a022e7ea25fc6ce0eb7c51d2/uuid_utils-0.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32df1944808877702ceea398c103881c09a679bb672a215e01c2a84231266bf9", size = 320025, upload-time = "2026-07-09T13:48:48.208Z" }, + { url = "https://files.pythonhosted.org/packages/f7/2d/bdc2caf9719d9090d7c46043242ae6136cba4f7a7ee384992ab905ad9aa1/uuid_utils-0.17.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:98c88d3edd08e7245562e9815996dbc6f0bd4745e1c76462f24af5ae4e187dd1", size = 327931, upload-time = "2026-07-09T13:48:49.673Z" }, + { url = "https://files.pythonhosted.org/packages/b6/33/9219d09d51ead282b578b2a4e0a515c2cce3ec52076cada8bfb7e35727d5/uuid_utils-0.17.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a4370089c8b2e42f1db51d76408c7fa8eaa2934bf854d17983d16179c07c098", size = 438537, upload-time = "2026-07-09T13:48:50.842Z" }, + { url = "https://files.pythonhosted.org/packages/d8/79/e8e0f8b3955f2081c116157119d87659937893242eb834aa170da04d660b/uuid_utils-0.17.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09a55b7a5ae764985cb46467496a1787678d0a1400356157a080ad95b1a36869", size = 320656, upload-time = "2026-07-09T13:48:52.164Z" }, + { url = "https://files.pythonhosted.org/packages/d5/5e/d1ceddc430ff04b6e21704b2030d4438074a2f478b265dab43da957791c1/uuid_utils-0.17.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:56aa6488b931246fae11924e4bd0e2b32677e63945eecb71c29e3c2ca0dc3131", size = 345310, upload-time = "2026-07-09T13:48:54.076Z" }, + { url = "https://files.pythonhosted.org/packages/d5/62/89438e12f389a843e626b7e37691319a057b3d6b80914609106891faadda/uuid_utils-0.17.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:309a35f12d99dde19032bc2259cda6431c85eeac0879134dc777cc3087d7e1cb", size = 496771, upload-time = "2026-07-09T13:48:55.365Z" }, + { url = "https://files.pythonhosted.org/packages/87/d2/eedcd99f522d60e238ead03844f0d51743ba84d33044959e230b756bf212/uuid_utils-0.17.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:21c79b61ff750abcf057163dd764ccb6196cde7a26cda1b31b45cd97769e03b3", size = 603631, upload-time = "2026-07-09T13:48:56.746Z" }, + { url = "https://files.pythonhosted.org/packages/0e/a8/bb1b38aaddd7243b6e562c6694f499bf094800918316192fd8cb2cdc2620/uuid_utils-0.17.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4134353bfe3026ddab8e886002dc52bc5a0ab04611aabb0eaae23c32e6e57f64", size = 562008, upload-time = "2026-07-09T13:48:58.241Z" }, + { url = "https://files.pythonhosted.org/packages/b4/77/5f7ed930dc105e293845c09e4d5bd84076318a12f45a46783e1af64906d7/uuid_utils-0.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7c89359affecebe2e39e6a116d069b363c936511a9572b308402489a26957d89", size = 525527, upload-time = "2026-07-09T13:48:59.784Z" }, + { url = "https://files.pythonhosted.org/packages/fd/25/1b55697adf6811a6f92cff6340e6b03e31fd6bc51066a5c10698c29b3679/uuid_utils-0.17.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:6a019a31bc4db89a0903a3e4f6b218571f3a6ff0ad4b3d3fe1c8f91a05ff6e3e", size = 97965, upload-time = "2026-07-09T13:49:01.217Z" }, + { url = "https://files.pythonhosted.org/packages/26/bf/cd729343de4684230be8a966bad7bfc2cf10ce3e643b1189a8b5370dbe35/uuid_utils-0.17.0-cp313-cp313-win32.whl", hash = "sha256:b3131a82d0c7611f0aa480a6d36929e001a3f54ba0fc029a8118a5863cce513c", size = 167316, upload-time = "2026-07-09T13:49:02.354Z" }, + { url = "https://files.pythonhosted.org/packages/76/f0/e602ae0a1b139a7826e5189b93d91902564def06d5006324fd2faf82c8fc/uuid_utils-0.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:9e311f908d2f842fca4c7dcebc4f10306b8089b204ef04cf6704b4332c9ff6ff", size = 173630, upload-time = "2026-07-09T13:49:03.529Z" }, + { url = "https://files.pythonhosted.org/packages/1a/52/024ebece265b387154115dc4f1d9727174ef82623069f4bec8b7ed7e73f7/uuid_utils-0.17.0-cp313-cp313-win_arm64.whl", hash = "sha256:c351737e2e65497c7200ab4ffb8af97e9f48be6488309abdd265fe08d66ee92f", size = 173214, upload-time = "2026-07-09T13:49:04.836Z" }, + { url = "https://files.pythonhosted.org/packages/56/44/e2fd3fdf356e1b55d2acf1b956b4f3f29ffb215a99c387eba04b1c5fba66/uuid_utils-0.17.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:673d89cc434cc9b97a0b4cf61272f6fca70a81f64eb0afbface2a0d9f77f06cd", size = 562232, upload-time = "2026-07-09T13:49:06.201Z" }, + { url = "https://files.pythonhosted.org/packages/19/28/65e0980d668a6d44e699f59d1acf43d6b5d4893592c115ce7c680bb4dfa1/uuid_utils-0.17.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:387cf7437c94ddec08651a0f1081381299c7075bc48a6251d8922bf39973378a", size = 287858, upload-time = "2026-07-09T13:49:07.45Z" }, + { url = "https://files.pythonhosted.org/packages/8f/8d/5e97bcebc90fb6a10f98af3dc1ba552e04183aba59e2edc0b9cf486dd998/uuid_utils-0.17.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:220b52746d99e11964badac3c0869016e0c24bafb70a7dd5c2c072a6be3da9cc", size = 321587, upload-time = "2026-07-09T13:49:09.489Z" }, + { url = "https://files.pythonhosted.org/packages/8b/d7/88b2a2370cc3d455ba0515fb6f5c8f7ac0c0f55a86801b6e56a432f22c17/uuid_utils-0.17.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0ab4a66e7a035ad6625cfc1fbdb34f5c2d25a80ae1ef4bfee458ea2036333c6d", size = 328964, upload-time = "2026-07-09T13:49:11.292Z" }, + { url = "https://files.pythonhosted.org/packages/bd/0f/181c5da673953dfc0958cb4fb3a4984a9098673ddb05cac68e994bc8511b/uuid_utils-0.17.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5641071337eb11d61a001ea08793bf72216f3241f0a433ed2764804b2a3e3cc7", size = 442909, upload-time = "2026-07-09T13:49:12.644Z" }, + { url = "https://files.pythonhosted.org/packages/ec/38/5c5e665af542884a8fd3c61725c38453239e13940326b5b70f3ef8881a97/uuid_utils-0.17.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9082e709014946b1f6e96ae6ecd93652efca2d2a6a3ab67dbe151c8b4bf193a4", size = 323076, upload-time = "2026-07-09T13:49:13.897Z" }, + { url = "https://files.pythonhosted.org/packages/f5/35/7de97de18cbf226c2a4f2104ad15e56ca4491717c81c0b71795c0c585b4e/uuid_utils-0.17.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1fd6f0e8a162dc0e9255b6aebe3cd175e76c33202f1bf39da9e6294b93db0099", size = 347360, upload-time = "2026-07-09T13:49:15.237Z" }, + { url = "https://files.pythonhosted.org/packages/26/a1/9915d5dd59fdd1957ded5d188c0ea0b9db5a1d84d42c8d8828a7b83b366e/uuid_utils-0.17.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d63010803d7c368963bbe6f7ec379593e76dd581d7db0f29118d88713c9e0354", size = 499267, upload-time = "2026-07-09T13:49:16.774Z" }, + { url = "https://files.pythonhosted.org/packages/c0/05/88108405262ec850cea0f95733445d6873e5772af3292baabd9ef8457740/uuid_utils-0.17.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a46bedc273b6f58f11dee816ff74999625ef8d007890f411b7a4975bf1c89330", size = 604940, upload-time = "2026-07-09T13:49:18.147Z" }, + { url = "https://files.pythonhosted.org/packages/89/d5/6dbcd300de47cc443cff2656cd5327a385751213dcb2101cfee7388170b2/uuid_utils-0.17.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:405233a5f625b3d995648f4647fa6befa4567cf3f74e1f6b9837e16f7310f0e0", size = 564172, upload-time = "2026-07-09T13:49:19.593Z" }, + { url = "https://files.pythonhosted.org/packages/ab/94/e8057f2288a415fba8a978bca4b589f5cb6b91a028a5dc07a1775938b33f/uuid_utils-0.17.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b6c5d2d71e1f17329150ad9427d27f4a3f29a01792e7ecdc64a98ac5368fc4d5", size = 528533, upload-time = "2026-07-09T13:49:21.075Z" }, + { url = "https://files.pythonhosted.org/packages/f0/6b/31713148c77e48e62f51aa042a98a54a8be0396912ea5130f83f52ae722d/uuid_utils-0.17.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:f7e9b8728ba07a3cb2f29d5aa1a266c2664eb8ef0fd43afa34627c92f7fac8f0", size = 99197, upload-time = "2026-07-09T13:49:22.351Z" }, + { url = "https://files.pythonhosted.org/packages/f3/f3/ca6f6ac5428312df8ed632f6dd9f9e6aba23090471fcdeae53eab027e8b3/uuid_utils-0.17.0-cp314-cp314-win32.whl", hash = "sha256:58838921e377791ef22c64cc92141bfae030f43651ff9272f0f28a208a9e6a5a", size = 169540, upload-time = "2026-07-09T13:49:23.563Z" }, + { url = "https://files.pythonhosted.org/packages/c6/cd/7ede0db66411fa09817d79b680f7454ea9bee2d374e1922e4efd065760a3/uuid_utils-0.17.0-cp314-cp314-win_amd64.whl", hash = "sha256:42275ebd0e8e74e32cdbfb8bd88fc99576567d51d54a508020611fd8f4f463a0", size = 175984, upload-time = "2026-07-09T13:49:24.703Z" }, + { url = "https://files.pythonhosted.org/packages/f0/81/533b5f80cd4918c0693f4e1b7b90ceb1caa45f4266ae8b528135d7ecca5d/uuid_utils-0.17.0-cp314-cp314-win_arm64.whl", hash = "sha256:b5d11cccba076a32321ef1380dea956821f0b51794ef59df64e58fb1cd543aae", size = 174749, upload-time = "2026-07-09T13:49:25.886Z" }, + { url = "https://files.pythonhosted.org/packages/a0/13/f400ac39d06fd8be5b099c09e41bb975205926722a3e8d53348817cb7ff9/uuid_utils-0.17.0-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:fae8b282f0cb22a5de222999f7723f4e5ec04f6fcdf4aaef879b5b36625ae2b0", size = 562610, upload-time = "2026-07-09T13:49:27.374Z" }, + { url = "https://files.pythonhosted.org/packages/03/8c/c71c8312304c56f6d0bcba87cd402fa79bec35d18ffc8c41954196ca68e5/uuid_utils-0.17.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:967955620df45e6cffe2e9950cb9903cb455649396f896b26b04363a91a5054b", size = 289473, upload-time = "2026-07-09T13:49:28.989Z" }, + { url = "https://files.pythonhosted.org/packages/bb/cd/522117e2e5184ca1d4f0f85ee833e9e21bd8c6b99eff8a4d1a8e5a194e33/uuid_utils-0.17.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:375cde148430d60a4a07c03abaa0774c4fddfdd90de99b4ba02f24088bc9d750", size = 321600, upload-time = "2026-07-09T13:49:30.4Z" }, + { url = "https://files.pythonhosted.org/packages/6d/f4/0d81f9bd346fc717bc561c08fa6457e0328966eb76e536b938fe77d56459/uuid_utils-0.17.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:975c17da26c5b9d46c336b03c52a057ac28378d6f9d98b58d32a038589bb3912", size = 329569, upload-time = "2026-07-09T13:49:31.732Z" }, + { url = "https://files.pythonhosted.org/packages/5e/41/26e1363f36a94c9e8ec2dd21d5f63088d3e7c723adbb12dcc8fdc77be417/uuid_utils-0.17.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3150d836290c88f1d26eb59c4db280d87417dd3bfaadd2889c77416c8f0ff6fa", size = 442051, upload-time = "2026-07-09T13:49:33.024Z" }, + { url = "https://files.pythonhosted.org/packages/2b/a7/2c1ed1b34d7df7fdcc11c28fd26d94d44843b37d9af2435ff9fd8abdbc08/uuid_utils-0.17.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9472a8de37faf8bd216c628e0e68c8f6bef730d3ba0a5060f3b0fa460c992ac2", size = 324372, upload-time = "2026-07-09T13:49:34.554Z" }, + { url = "https://files.pythonhosted.org/packages/78/bf/328d3c6bb22c496944a1b3b732207d71aa6964eb604e5e3b9dcb91ed0a00/uuid_utils-0.17.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d27c531edb8d1f38ca2eddaa1fa24913a460aeb721f2efd4ef42a124ce94e354", size = 348548, upload-time = "2026-07-09T13:49:35.898Z" }, + { url = "https://files.pythonhosted.org/packages/3e/76/a07de5cb7b90582fdbbc830fd19be129cbbb9897cfe239fef469d7bd2d09/uuid_utils-0.17.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5670c52a438e21483ce715776144914a4e2a2a5c62d9dee15f8a3e90cf128ae6", size = 498985, upload-time = "2026-07-09T13:49:37.142Z" }, + { url = "https://files.pythonhosted.org/packages/f4/62/9966e46ae34fcec6b06119631fb3c09705ea78835035ce3a82d3348eb61a/uuid_utils-0.17.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:6f29689a76fe7a49cbd629a794d0ec1eab48814e323a00a146a741b0195bde68", size = 605183, upload-time = "2026-07-09T13:49:38.648Z" }, + { url = "https://files.pythonhosted.org/packages/d7/4e/bb962ba0fe31e903b199f22cf4c1a6cba35a8987aef526d287277ab8ca8b/uuid_utils-0.17.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:4441600447d340ae103a353f01dbcd22ff680e5ee1a22988efe8d7b791d8fdb3", size = 565412, upload-time = "2026-07-09T13:49:40.115Z" }, + { url = "https://files.pythonhosted.org/packages/ce/9e/122adfeeeae8a84ccfd43bce627b104d12a2180a93bffd2c0e1b54dad7a6/uuid_utils-0.17.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e7b04935a79c03c41ad08d0a5f390aac968bfb561f1268897bc5b0f077971efd", size = 529885, upload-time = "2026-07-09T13:49:41.513Z" }, + { url = "https://files.pythonhosted.org/packages/b3/4f/257304dded339dc35fc9bf35722ac68fd4fdb930f255b8f7bccdf74ebba9/uuid_utils-0.17.0-cp314-cp314t-win32.whl", hash = "sha256:239d8a281fe10bae33205b5d43185834d556b18434e0a113b5dc1dfb2fd97e91", size = 169472, upload-time = "2026-07-09T13:49:42.871Z" }, + { url = "https://files.pythonhosted.org/packages/35/c8/e78c06db7e9ce317ce7b8759ff2058333eac75caa8c22b75f0059589c9be/uuid_utils-0.17.0-cp314-cp314t-win_amd64.whl", hash = "sha256:e288a06cbbbcd01b44386e767985c9e21d2ad9bf59829aa7058d9a2a494804ab", size = 176271, upload-time = "2026-07-09T13:49:44.105Z" }, + { url = "https://files.pythonhosted.org/packages/a7/11/bd1c70e1ad3301163cebe66c8d26de26e6814d52f642a849448bd2833626/uuid_utils-0.17.0-cp314-cp314t-win_arm64.whl", hash = "sha256:1776a80d16369999b21627028cc5dbce819be83e1e079fdd7a51b587d2916db9", size = 175004, upload-time = "2026-07-09T13:49:45.591Z" }, +] + +[[package]] +name = "websockets" +version = "17.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/96/e01084f83a64bcb3a27994bd0cb0db68ff29d9c6707fae37ec19b18ba990/websockets-17.0.1.tar.gz", hash = "sha256:5baa9bc0dfbae8c507e51c8cf1b6d4628086f7a87bbd3a9952bd5f035451f1cc", size = 183298, upload-time = "2026-07-31T11:31:27.665Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/50/ff/6199a52d864215750af8668d84b0274775011a90052081f5a9495807a92b/websockets-17.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:10f461191125c63902ea7394ae9e752b1b5785641850c1d365bb30b0f88bc53f", size = 212603, upload-time = "2026-07-31T11:29:30.771Z" }, + { url = "https://files.pythonhosted.org/packages/54/7e/439a962bcada88dcf586da77a1b2385f91e2d2910e9359540934c827156b/websockets-17.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cffc84ddec6da7f447677266fee2a3c40ecc78172f00752aa1150b8a8d65df1d", size = 210286, upload-time = "2026-07-31T11:29:32.157Z" }, + { url = "https://files.pythonhosted.org/packages/d9/82/123660edc759c225626b3b91952c7625f85c77a8362acbc35a4623120f7d/websockets-17.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c23e532c8a2325a1e7486de8763a60dc43e83f01bcaeca07e3ba79652c156db1", size = 210549, upload-time = "2026-07-31T11:29:33.388Z" }, + { url = "https://files.pythonhosted.org/packages/cd/2f/2940e57080cf56f28190287516400126d5a76b52b9a61dc10ba6f6400dbe/websockets-17.0.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c09e097d0e46e3c289bedab9a475ae344b70c30ff5646e46af22b4e6fdc97b21", size = 219874, upload-time = "2026-07-31T11:29:34.608Z" }, + { url = "https://files.pythonhosted.org/packages/42/28/9ec976c16d63cc51c28dfec74b66854048c0b8b6579946e902f91b69e8bf/websockets-17.0.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f47b0815af3948ec6a440b3afa02f05b18cc0939549e91b5c677b5d9c2c8472a", size = 220150, upload-time = "2026-07-31T11:29:35.831Z" }, + { url = "https://files.pythonhosted.org/packages/f4/a4/850c699a16bbc451723856360c59bd997bec075e637154f3fa96e80d5760/websockets-17.0.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8848c207049ad49d318e5f64a3d4d7bb189f8328d0d98e65647788f2a085785c", size = 221389, upload-time = "2026-07-31T11:29:37.189Z" }, + { url = "https://files.pythonhosted.org/packages/47/e1/f60a891c1a4b3420d5052333a84eb7241e1fb4a71866dec1562f5fa30027/websockets-17.0.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2604de7228506b13a44a256a9d223943340c0e725af5d367dc068e192b027761", size = 224169, upload-time = "2026-07-31T11:29:38.61Z" }, + { url = "https://files.pythonhosted.org/packages/26/fb/e2a893be6fae4fddfe50ddc3035a331d3f381103d5467b7900026bdb3a64/websockets-17.0.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:07abc3bd196a48af476a82fd47f3f79a6a3f70937a9f930cef703cfa0c9d83b6", size = 222025, upload-time = "2026-07-31T11:29:39.897Z" }, + { url = "https://files.pythonhosted.org/packages/d9/72/e3144b2d79276fab9798ed7d4aea2f0847434f186800b6f56a1eddcb3114/websockets-17.0.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:769ce7e2acfd9a89f2bed3a9c0da229459516bbc00bd4c9e2ca492c613ae4861", size = 220779, upload-time = "2026-07-31T11:29:41.084Z" }, + { url = "https://files.pythonhosted.org/packages/c0/5e/69c02174fbcf1c40c6adc45d3c316a401558392fe7bab8969ef8c46f1689/websockets-17.0.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:07d78a509c3333f5908c83d7f78144ea68a6c9ec28110f5c54d81d8fcdc262c4", size = 218053, upload-time = "2026-07-31T11:29:42.322Z" }, + { url = "https://files.pythonhosted.org/packages/b3/09/7574778b095b99cfa0856583462f56568df784f9b41485145169b2ec9c64/websockets-17.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ffad64ce7ad3703d652a3fd9af26238377d24ce52c6ad8ff35d26d82f61f493f", size = 220825, upload-time = "2026-07-31T11:29:43.553Z" }, + { url = "https://files.pythonhosted.org/packages/c5/e6/f46571f38765dbc4cbc0d0b47de8db65768006dbbd4340e6f5f51bc1d895/websockets-17.0.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e95e321d0d763f2b6633512605f6112ebd70d5746f3ce05c941909d4a25233f2", size = 219427, upload-time = "2026-07-31T11:29:44.731Z" }, + { url = "https://files.pythonhosted.org/packages/9d/31/6ff1fee057bd7e9dd5237fc064a749615378d003aa045b5bfc2d12b2f4f7/websockets-17.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cd526c8228e759c1006c4b7c9ac71dc4e925ced1a6a6a5a8e94643709738f63e", size = 220198, upload-time = "2026-07-31T11:29:45.997Z" }, + { url = "https://files.pythonhosted.org/packages/7a/4f/d41847227a44b9ad87c3d5a9fddbfad8b7c4d6032878d8460d9d37c2d44f/websockets-17.0.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8cd3369e42c0246afaf9d669cfc19797e3a49e8c0a639544459c57597108b966", size = 221304, upload-time = "2026-07-31T11:29:47.314Z" }, + { url = "https://files.pythonhosted.org/packages/63/30/21a7e326c6ad2eb526cd5b816383d59cdeb28b8805b65a543c3cfbd8e8ce/websockets-17.0.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:b580794e926cab7ff42ee4371ef14e0b22cb2bb722a607f77769136468f49a3f", size = 218858, upload-time = "2026-07-31T11:29:48.587Z" }, + { url = "https://files.pythonhosted.org/packages/2d/48/55b0331cd5bec9ce29748f79edc00075805450a47011d0c8e3b1c61dbf04/websockets-17.0.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5033ffe6804dd53afafa7d08e8c3eef2d2431f34d58ca30507a8442dd04a033a", size = 219840, upload-time = "2026-07-31T11:29:49.791Z" }, + { url = "https://files.pythonhosted.org/packages/78/6e/2e8bc06e546f49b32a58a2bc2957902d1809ecc37552d3d7ccd6639a126e/websockets-17.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6db9e5bf3649ab506c6ae8a3ac85a00fb1ae3816d75962771b2df8adbc5d40d2", size = 220116, upload-time = "2026-07-31T11:29:51.026Z" }, + { url = "https://files.pythonhosted.org/packages/b0/ad/4bac01fa41aca54307157b9c9f68b066a6bb51fb18716ba618078a67b283/websockets-17.0.1-cp312-cp312-win32.whl", hash = "sha256:bc0bca48ba24c6c866847fd20478a51dd547fa0ad258dab9615c414ec534bbc0", size = 213050, upload-time = "2026-07-31T11:29:52.328Z" }, + { url = "https://files.pythonhosted.org/packages/82/d8/c3a78cccc74a554780e9e76e323d5cde891048627025f0f82623e22dc3df/websockets-17.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:2b3f3020171202b135ca078e20434977c6b2b02af647130d6980c9e39b9462e3", size = 213348, upload-time = "2026-07-31T11:29:53.891Z" }, + { url = "https://files.pythonhosted.org/packages/7b/25/e1b8824bd632c8a5a62d504b61e9e35e470b67e4be0206f5c28f90c7f86d/websockets-17.0.1-cp312-cp312-win_arm64.whl", hash = "sha256:41d6aa06b5ab832aee72fedf47a149535b121ac900b6bb4d3fe14712afac9a79", size = 213276, upload-time = "2026-07-31T11:29:55.299Z" }, + { url = "https://files.pythonhosted.org/packages/ba/a8/79c577bc2f874ee22f6f5ccdab97ba9ce6b96806be3fcc3a6d8490f88a21/websockets-17.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:55b12e47dcee83673a40d07686cfb6f9d6dfc285976ade9463f61d2bef3fad22", size = 212593, upload-time = "2026-07-31T11:29:56.518Z" }, + { url = "https://files.pythonhosted.org/packages/db/99/e1cfaf419bb3b2fcfd6792a846f1d936293132b0b9a56530ced016c83c7b/websockets-17.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c1c118a6b0e25bfc9a6802075d748fa6321714ffbdf3c88d29d9a0e3c7386c75", size = 210280, upload-time = "2026-07-31T11:29:57.768Z" }, + { url = "https://files.pythonhosted.org/packages/a2/ef/cc994494bf7d97e41833f6ff55c24f535e4d527a10370b9631737e9c2f00/websockets-17.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:734d20364dc2cfe03674883cafcf580b6e431c5ce42b476312b9285310230cf9", size = 210538, upload-time = "2026-07-31T11:29:59.021Z" }, + { url = "https://files.pythonhosted.org/packages/87/32/fbf2d132f63ba3e67f675bccf333469786a24e0418969ce1d8e6ff9e6f02/websockets-17.0.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9493314a99e599163c854fb5900ad7f7ea38c5cb9d9103aa30b3c6b8181c01fa", size = 219925, upload-time = "2026-07-31T11:30:00.298Z" }, + { url = "https://files.pythonhosted.org/packages/16/50/64eee3d25a47fe744a9490e0627cc373dca096755db740f91c28bd61cd35/websockets-17.0.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:18ded646ce98cdd3c0235825b3252f1df55765ba49b616bb10282f758667b4d0", size = 220206, upload-time = "2026-07-31T11:30:01.52Z" }, + { url = "https://files.pythonhosted.org/packages/15/56/10ed4bc4dd75f204e3c62bd4898e44a8742a27773c80b188cfa7888aad2d/websockets-17.0.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c1bec5d6a19f5fbe87e4940739cfc65e7bb53d8b353e1029b8037a1653b321bc", size = 221445, upload-time = "2026-07-31T11:30:02.788Z" }, + { url = "https://files.pythonhosted.org/packages/bf/be/bb14328614c068ab09569962fbf218fc00413ce3febc6d2684c764b6f37e/websockets-17.0.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:872273e629ca7e3d35f16a2dc6ede84e1d5c831e616b8277de6e4f83114e7c58", size = 222887, upload-time = "2026-07-31T11:30:03.943Z" }, + { url = "https://files.pythonhosted.org/packages/32/1b/4cb0eec2fee310007104687493175af190019f705940c864f9c523fe9f6f/websockets-17.0.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1df81d174c1561292de9e40b141cafc04f69077272f6c352afe1d743e20810df", size = 222072, upload-time = "2026-07-31T11:30:05.258Z" }, + { url = "https://files.pythonhosted.org/packages/6c/9c/14e6391de777ddb39c439c450deb551406d445e25a5877d6fa25c49d4544/websockets-17.0.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:759adeb5b0c5775b563254ec63b5b79089fc0045b479143a0b1b8c0ebaae1253", size = 220826, upload-time = "2026-07-31T11:30:06.53Z" }, + { url = "https://files.pythonhosted.org/packages/cb/57/96e94e384442247bbed5d3ab67381c7257355c2d66b62c3ad33a17f5d385/websockets-17.0.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4d1d99db29b5444e3982f1ce2ba8a833508ad44b2f1fbd0bd99e81d825c0b461", size = 218107, upload-time = "2026-07-31T11:30:07.766Z" }, + { url = "https://files.pythonhosted.org/packages/c0/8c/9c9dedd14c3919435df9b35cdee7111268c751252b87652f3a6a4f56e760/websockets-17.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:02ed63bf26dda9fa27df730a41f6664586c4ee05972c8fb667ce1725b3fd13d3", size = 220889, upload-time = "2026-07-31T11:30:09.035Z" }, + { url = "https://files.pythonhosted.org/packages/94/4d/ca73c2ac82c00f50c529784bacb323e42da4816333211bc1543d90c9cf11/websockets-17.0.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:eab6de8a98b9a7772cf686d00b4de439fc7efb8ab05ae106ef227291d06f87c5", size = 219486, upload-time = "2026-07-31T11:30:10.289Z" }, + { url = "https://files.pythonhosted.org/packages/5b/da/fb37ac09dcd7c69dd73bac979ed393df35f78a3c232e293d1ff3bd586d24/websockets-17.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2a855b6dfe21c4d3420be265ae031829ba8ba0be0ea350d9f7c3ef30ae63ebe2", size = 220258, upload-time = "2026-07-31T11:30:11.605Z" }, + { url = "https://files.pythonhosted.org/packages/fc/04/9693f191d968a93f37326a17301a101d49580889c688f466699f89ecdee1/websockets-17.0.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7002d5f9e1c3ddd991cdfdbfee18cc8c8b196b2445022892badacd6cb338bbbc", size = 221358, upload-time = "2026-07-31T11:30:12.858Z" }, + { url = "https://files.pythonhosted.org/packages/cf/29/ad0d85c01db5dcf22898d51648bd2c25af0dd0a4a41c550b11acddeeeba7/websockets-17.0.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c395bda8e7d8f51a02e80261fb57127979e5c472675d9a96b2860619ad47da48", size = 218921, upload-time = "2026-07-31T11:30:14.064Z" }, + { url = "https://files.pythonhosted.org/packages/18/3b/bf8e855e495dcca63f2b8aa019cf2ada3160e1fa66d833c7417f3b1f7f38/websockets-17.0.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aadc298969ad229d8e3029fc5cc751fdad286696230f9cf014e90ff9cd8e6ea0", size = 219871, upload-time = "2026-07-31T11:30:15.358Z" }, + { url = "https://files.pythonhosted.org/packages/3b/db/c7abd6639a93a40279cd1ddc57e09e1c4f8381c4cfccdb775aa5aac9770a/websockets-17.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f11a398d8170b7ac5000baf7f258dcda579ef3ea744e0cc6a165e0dfbc0d3198", size = 220154, upload-time = "2026-07-31T11:30:16.96Z" }, + { url = "https://files.pythonhosted.org/packages/f6/2a/25a9f8f2e5a6ef34e911d2f55d9f756bdeb92b4c28cfb77b8430bbc73cb1/websockets-17.0.1-cp313-cp313-win32.whl", hash = "sha256:846a4a8b0833e3cad57523d9e3bd50ec8ea05ab9d06c582f82a1340ba096af5f", size = 213038, upload-time = "2026-07-31T11:30:18.434Z" }, + { url = "https://files.pythonhosted.org/packages/81/2f/ea1380f72bb11b64fc5bc7ae0d42de5bbf3e6dc13b965706b2a1d4e17cdf/websockets-17.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:409d93efcaa14f7a99592c5baaef5ec6ca94fba0f5aec1a86f693977c69c9c1c", size = 213348, upload-time = "2026-07-31T11:30:19.693Z" }, + { url = "https://files.pythonhosted.org/packages/e6/c7/b956ed9151c3c74530ebc62d716fbfdbde7507a6acc6423a64f9ecfb6b8a/websockets-17.0.1-cp313-cp313-win_arm64.whl", hash = "sha256:90246fa9e6cb192a778ce6ce024057ec54317a894db7899c922dcdc1f4cbf6a5", size = 213282, upload-time = "2026-07-31T11:30:21.045Z" }, + { url = "https://files.pythonhosted.org/packages/98/dc/cadab608924ac605647031472fb1f8792d7d4ea07565ba1899ec42028e0d/websockets-17.0.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:53b90c00bc6201ab6695c7ff51a04d0e425514c37515e9eeecd2c1b978ac6c0e", size = 212640, upload-time = "2026-07-31T11:30:22.436Z" }, + { url = "https://files.pythonhosted.org/packages/16/7a/b034d13ca181211bbd58bb50835cb196a7784cd505b5a2079d4d03374f9f/websockets-17.0.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:5f33a649bfcb8312524173cc4bbafa7dbb236e18eee9aa31a1d324ca0ddda28c", size = 210332, upload-time = "2026-07-31T11:30:23.608Z" }, + { url = "https://files.pythonhosted.org/packages/2f/4d/943ede39b53744768edf1ed84a3f9401527388228a3d6c1249c02c3d6bd7/websockets-17.0.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cddc675ec31bca65473321f9a9794e488b43b3b8de5d02c8ef4810c5d5792163", size = 210546, upload-time = "2026-07-31T11:30:24.932Z" }, + { url = "https://files.pythonhosted.org/packages/cf/e3/88dc159d2ae66743c669443246243f28d873b0c5e58271b8cc1ca0440334/websockets-17.0.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b3ff0ad440ad52dda64138f16895f66403f40192365e39b1010e889f289746b0", size = 219928, upload-time = "2026-07-31T11:30:26.221Z" }, + { url = "https://files.pythonhosted.org/packages/fe/f2/ff27eaefa15851a5cf7f004ab827a022bf2d6632cb520f89cb100db7e84b/websockets-17.0.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:72d7f2a5aeb4e82daa4ee18f125b4277f427033359be5c745ad709608446cc2c", size = 220279, upload-time = "2026-07-31T11:30:27.49Z" }, + { url = "https://files.pythonhosted.org/packages/19/2e/a5166149f363d2449c1cb2dde6486a245521979509d53b87a09f3e79662b/websockets-17.0.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6fd88365da261c53d3e943fb37e0d0721b9cde119f6b2e3fc84369b6ab234d63", size = 221525, upload-time = "2026-07-31T11:30:28.872Z" }, + { url = "https://files.pythonhosted.org/packages/9b/b5/f46931269b3ff3bde65d27c65ddb22f9bb8ce92ac2c6c4df0910128f6219/websockets-17.0.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ab9f962a5b64a5c3c845d556b7dc4e6fb683f7b67179f8205e814bb2e0213ffe", size = 222897, upload-time = "2026-07-31T11:30:30.164Z" }, + { url = "https://files.pythonhosted.org/packages/42/f4/deccf3439f35df953ec35e13fe07986821c5f1ab5785d69614283bdb9034/websockets-17.0.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8c07f145d0b9e90cbd96035f31fb79199aef4da1872854e36ebeb258e3d57594", size = 222129, upload-time = "2026-07-31T11:30:31.489Z" }, + { url = "https://files.pythonhosted.org/packages/35/a5/e1b57a59da92ade37fd021567a17b518ea8267b28e5530075844cdb525fe/websockets-17.0.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9f7747d3daa41a11f25f7cca5dc988fc51da97b311bed4c9d843860f79779283", size = 220875, upload-time = "2026-07-31T11:30:32.805Z" }, + { url = "https://files.pythonhosted.org/packages/f0/30/e7d0889c790a854156de424575fd67af79ddbaed9ff3157ae863dfd1c1dc/websockets-17.0.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2abb1ba0a5133b7d2ef3c1c9f4b0c1e8a101012dce0b594ab2b2888d9a64820e", size = 218160, upload-time = "2026-07-31T11:30:34.512Z" }, + { url = "https://files.pythonhosted.org/packages/09/2e/43db785d6ed9ae7594fae7b62bbc9cb4dfee2b015e06a1005f1e5ce283b6/websockets-17.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f3fd9a1f87f8f0f3f8e9f9bd0195f7516562d13f5b178db8c5784d1f60b60bed", size = 220951, upload-time = "2026-07-31T11:30:35.806Z" }, + { url = "https://files.pythonhosted.org/packages/eb/f5/4ac3cab3d5e8a830657a822f64a8910e3803229c6783e59c3fd9a3487427/websockets-17.0.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2bc14b481e05e331811108daa1aeb41a5e237a5564ef2f02ec5a356a0f102f78", size = 219460, upload-time = "2026-07-31T11:30:37.273Z" }, + { url = "https://files.pythonhosted.org/packages/03/0e/c3a4020673ffc17c82cf1a467835038a196a555d3b4f2a50f0f063cf8ccc/websockets-17.0.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:57d2ee9b24b404ce75f3814f92073c0ed88106c950148d2427fe8d25ca254d1f", size = 220248, upload-time = "2026-07-31T11:30:38.527Z" }, + { url = "https://files.pythonhosted.org/packages/7d/87/e47a6a278cc1dfade38444c893ce18322943c25d4b780a74450d9d164be1/websockets-17.0.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:1b363bfd72a52c0658a3154a4cff219f15a474b35a235057d38853bf151acce7", size = 221421, upload-time = "2026-07-31T11:30:39.879Z" }, + { url = "https://files.pythonhosted.org/packages/da/8f/473d5fc4e3836e375b0233c6ef26777e6e5e3f7bfc84ccd524eae4090ed5/websockets-17.0.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:10b1587c599fa0f2c89154587c80e0fda98ade6c9fa8c0260a2823fb1800b685", size = 218975, upload-time = "2026-07-31T11:30:41.192Z" }, + { url = "https://files.pythonhosted.org/packages/d4/b9/819ec2dcdf69031d7e9cab11247f3a6ff9bbc8c7c53ada1dbcb9055b227b/websockets-17.0.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d7d72843691f50b91127c50688df10cb72ec6f4c4b1d7e2c11ab33b16acf8e51", size = 219925, upload-time = "2026-07-31T11:30:42.524Z" }, + { url = "https://files.pythonhosted.org/packages/85/b9/6c0da301f6118502e079cf92f4e864adf28e56b3f8c0f6085076ced7b876/websockets-17.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:90973a3a00f23afdfd1c9b06fb84289bf0220f247ef8a62501a1967c7af54f7b", size = 220218, upload-time = "2026-07-31T11:30:44.04Z" }, + { url = "https://files.pythonhosted.org/packages/55/f9/cba32dc9dd856565263d6272f594255bd0e2781deb8cd982c026a54760ad/websockets-17.0.1-cp314-cp314-win32.whl", hash = "sha256:599b03beb77633bffc095334338fad79cafc2b01fbd58953838130a9ae967d7b", size = 212626, upload-time = "2026-07-31T11:30:45.579Z" }, + { url = "https://files.pythonhosted.org/packages/fa/95/91cdd8c192287d7ea741f37cf7d64fdc1a14410f06f73805e428a1a590af/websockets-17.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:81ce19c6046ace11da7001781be7317bb1dc389f399af4b2ed962190f76f9add", size = 212969, upload-time = "2026-07-31T11:30:46.983Z" }, + { url = "https://files.pythonhosted.org/packages/8e/fd/8c98a1e431960661c5769ab1a4dd66494e87ab02d791cc79e51e0d9a289f/websockets-17.0.1-cp314-cp314-win_arm64.whl", hash = "sha256:efe0ae052a8d023b87198921e8a7ce1dc7768816bcd2fbc20df171ac73a04891", size = 212850, upload-time = "2026-07-31T11:30:48.304Z" }, + { url = "https://files.pythonhosted.org/packages/13/c1/142f5186ee7dc3beee0426b998a79e223e067b7689afcaa95890d64aa800/websockets-17.0.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:ab56439c9f74c52770690c7b2f616b3bf775cb3920453ee355ac765c032d8bbf", size = 212967, upload-time = "2026-07-31T11:30:49.688Z" }, + { url = "https://files.pythonhosted.org/packages/02/de/4b03ed316c9dee180365286c298219809ff247be39beeaaf9958b21167ab/websockets-17.0.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:20a92f78ac8250984ed459faa9ca48c285adbfc0038ddc3fdac6046990a9c9ed", size = 210504, upload-time = "2026-07-31T11:30:50.987Z" }, + { url = "https://files.pythonhosted.org/packages/cd/d8/ad2b3e8f867e1e8cac3077e2f33ffb60b71bd763d6cfc71bd916f113c3bf/websockets-17.0.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6a434e59962a4fb9016bea327e1d14d6cd67670ecfb8942b4f4a0c24036634ce", size = 210702, upload-time = "2026-07-31T11:30:52.261Z" }, + { url = "https://files.pythonhosted.org/packages/48/18/7a77a82ce9d6f831c07b176da3942f7e71acd0f115f3ecdb1d00a040eb01/websockets-17.0.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2503c7e2a5049a12d5dac917a46d5d52591283a766165b8176bb167560421b38", size = 220290, upload-time = "2026-07-31T11:30:53.582Z" }, + { url = "https://files.pythonhosted.org/packages/f5/af/43c3e3c3ea7ba4693c2181743f3221957df28bededadcbd9fc8a0661bde0/websockets-17.0.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:28012a54510fe8301bb893ef143cec30a2780a2d3bc20b7bbdf4379d7a63945d", size = 220573, upload-time = "2026-07-31T11:30:54.966Z" }, + { url = "https://files.pythonhosted.org/packages/1f/bd/ed48eca15725743ee7e2dc172e15c61de29e85ec98dace7b14257f366836/websockets-17.0.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22bd00f8bae2bccdb5dbe41e20f58ba44ca9fff0b4b561aaf39099c35da762ed", size = 221747, upload-time = "2026-07-31T11:30:56.762Z" }, + { url = "https://files.pythonhosted.org/packages/99/50/838deb7937a8225c4925dd4a977eafea473fabf444178a99de0bc7e92bb0/websockets-17.0.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e98ec9ec61cce5bc4b8b218322ad090b0994eb060bb04da704c62ef0a3d864e6", size = 223891, upload-time = "2026-07-31T11:30:58.127Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e9/657fb70c6eb6bcd01adfa5d2b06496e9911e1c1a8813d353b8c00f7591cd/websockets-17.0.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8e387adb0c692c6b5571bdeafc8ac9d1901ea30f10309134780b16ecd35e6605", size = 222317, upload-time = "2026-07-31T11:30:59.416Z" }, + { url = "https://files.pythonhosted.org/packages/07/4c/82cb722afa5428fed981331210c4c07600570db01bb1620579f655b5adaf/websockets-17.0.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bd1470d2c53fe53269bf5619da7725d30dd9b9693f1689f7a85eab8dea734442", size = 221047, upload-time = "2026-07-31T11:31:00.757Z" }, + { url = "https://files.pythonhosted.org/packages/90/84/bd6d67d6bc65f0de0cb50de55dab42f256a9876a351c4736522eb168fda0/websockets-17.0.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:884af729b8ab50486acd94d9768c2b60914bf39b579ebba0a5cb73bfdfd61fd2", size = 218626, upload-time = "2026-07-31T11:31:02.48Z" }, + { url = "https://files.pythonhosted.org/packages/96/cb/6a372c8553976f0d8f97f5115826ed47e34b3be6b8bf0d0249af249a7416/websockets-17.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:a60fa1a25cca1bcc2bf87b8d6be37a741f0a3239fb5e9cfb7a37173b68ffcf87", size = 221299, upload-time = "2026-07-31T11:31:03.795Z" }, + { url = "https://files.pythonhosted.org/packages/bc/31/f966e8472337974f74d788b3ef6c6f3b8b9a5f201efd16a843c91d269fa5/websockets-17.0.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:e8208f2729cba030ff872a92064c97584eeb9502f53d32a05a0f05d5a17ca6c6", size = 219789, upload-time = "2026-07-31T11:31:05.08Z" }, + { url = "https://files.pythonhosted.org/packages/57/34/404e83a6cc7b0efcac810b7041bffd72ff76900e6fd0aa45a26c92fb2ffe/websockets-17.0.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:54cdcaa56f5d3eafd57058f0fa4a3de93a310b43a3c4699f06efc4c0bd054a5a", size = 220678, upload-time = "2026-07-31T11:31:06.635Z" }, + { url = "https://files.pythonhosted.org/packages/e5/70/8946188c2a68d67251859b589a3634918cf7867bf0b891347a5ecaa43d30/websockets-17.0.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:4d41c0a1d47a478bc432b3b9068097bee1ce0c5b19327ea6f75c2ab34ab1f2fb", size = 221697, upload-time = "2026-07-31T11:31:08.023Z" }, + { url = "https://files.pythonhosted.org/packages/04/16/ee73fc2083a2938ac6209f4ec804960496835b20a0068dbcfe8424957c04/websockets-17.0.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f991247276797d0c61ab7770bc9791eadc16f683b4d83517f624932adc1a8bab", size = 219390, upload-time = "2026-07-31T11:31:09.378Z" }, + { url = "https://files.pythonhosted.org/packages/94/6a/d5f88033c69932af6cdaa72da62516ade47c257e3bf69f4c0ba5f40e12a2/websockets-17.0.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:733e3cc7171fa1b899edbe725ef9382d0e960657dc1fd933f3281ae910c01dab", size = 220161, upload-time = "2026-07-31T11:31:10.915Z" }, + { url = "https://files.pythonhosted.org/packages/e1/2e/6183dd2c0370287ecf4afe0bb33aca364208e5e7b0e1a286adcaecc0c78b/websockets-17.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:810cb3fb5fa6e447216f4e82d9a85cb8aed0929ae3538153ddfe8a6e3121a58d", size = 220591, upload-time = "2026-07-31T11:31:12.289Z" }, + { url = "https://files.pythonhosted.org/packages/26/93/70f6516d85b9744f7eac224c4b1b9ef4e84133f80b53be02080cb1c3e663/websockets-17.0.1-cp314-cp314t-win32.whl", hash = "sha256:17ac37716c0244e82c9e384c41653c090b1864c6610224ca3857e7f7b58fce10", size = 212755, upload-time = "2026-07-31T11:31:13.883Z" }, + { url = "https://files.pythonhosted.org/packages/f1/2c/9d9c1da5a7ea9af307b386d25f64d1dead4729644198d2b92e36db5dfd41/websockets-17.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:bb31f42ea095ea826463c770829aa188a86c9a5c976b1467cbbf583c811de833", size = 213094, upload-time = "2026-07-31T11:31:15.367Z" }, + { url = "https://files.pythonhosted.org/packages/5b/24/a585e7573e128070605d003b5544729bcd58d9756c7e99d550818ca4b916/websockets-17.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:dbfae8e75b342e31fc6fd1a8bbb393b7cbb91d6cfd581650300a94381e7b7e2b", size = 213009, upload-time = "2026-07-31T11:31:16.776Z" }, + { url = "https://files.pythonhosted.org/packages/09/ce/3929538b2b9918f5eee623fbf3346893973191f6df93f19bbda097bd7bb7/websockets-17.0.1-py3-none-any.whl", hash = "sha256:c6be9cba65c65cc76dfa3d4619e359ff02a4476c74e179b215236c11a0b32345", size = 206718, upload-time = "2026-07-31T11:31:26.037Z" }, +] + +[[package]] +name = "xxhash" +version = "4.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/a5/1386f35da1475fcaeef42581deae73417c6d2a6a0b2d2e8914de18844dcd/xxhash-4.0.1.tar.gz", hash = "sha256:d55bf4ef10eb09b8b6866790e083d26d087d84caa3cc0946ba87c3ca7ecaf7b7", size = 101513, upload-time = "2026-08-17T08:24:08.557Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/6c/dc7cffeadd06336cd934947187cd38abb263103bbc552ca0f55fe4ff595a/xxhash-4.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1ee523f51718e41753f04f7102bb4dc55a18d2ea5cbaceef8ec7ca08571bd428", size = 38444, upload-time = "2026-08-17T08:21:54.332Z" }, + { url = "https://files.pythonhosted.org/packages/75/c9/cf736f6db8c3273af18925061572db0d4357818a9ce425f4b5fb0021918e/xxhash-4.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:515a822c73abbf6a0b7c70976d9662be342835c9d78b8dc7c023411f39c35dbc", size = 36195, upload-time = "2026-08-17T08:35:13.004Z" }, + { url = "https://files.pythonhosted.org/packages/da/a2/ca1929354b6851529d0148f7f335b5e2b0281f83bab3e19f0896dc579796/xxhash-4.0.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f5d031f35962e5483a613214e61f09fe24ab523062c3646d592dc16c4a217451", size = 253113, upload-time = "2026-08-17T08:20:52.152Z" }, + { url = "https://files.pythonhosted.org/packages/de/bb/542005206af59518bc8d78a210f1e0172217bc53beb32f64a5b632e72b6b/xxhash-4.0.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:da0264844a09b538c894e5eff25313d941deb4dedec2131b98418a71a3c9944e", size = 276525, upload-time = "2026-08-17T08:21:01.886Z" }, + { url = "https://files.pythonhosted.org/packages/1b/df/607cff25dcb0f1d35c3b04493f6ad8471edb03fd4eacbdcc5ceddef1f3e9/xxhash-4.0.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:1642907941ee4b75aacc3db688af52ea02ca2305ab22af7ee686ed726b332684", size = 297703, upload-time = "2026-08-17T08:21:57.958Z" }, + { url = "https://files.pythonhosted.org/packages/15/ba/9d2275eea0b9d9c6b02921be23f7588356c60df95c763b25f0e045894d43/xxhash-4.0.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4af350bc3f329970c0e3a59af84a8a30998bf8a9167eb50cd48e59baaa1d7bec", size = 280252, upload-time = "2026-08-17T08:20:47.299Z" }, + { url = "https://files.pythonhosted.org/packages/1d/aa/2299d9f6369e550aef2abb64945e39daa34412725aa46a20d99b74d76f67/xxhash-4.0.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8ba782ca3bf1e81492611152b9a0d5264971339e95e34d69de0ac2c926be496d", size = 511041, upload-time = "2026-08-17T08:20:36.771Z" }, + { url = "https://files.pythonhosted.org/packages/83/97/31bd8b8279e6935a0719f6910ced15e9d5a2cd554b253f6027ce1b5a1c2c/xxhash-4.0.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:237b8f63a2a0fcfb1ffc06e21dad23add44e6d354b2b014364a1d41e419a4dee", size = 261812, upload-time = "2026-08-17T08:22:00.469Z" }, + { url = "https://files.pythonhosted.org/packages/2d/c1/d180a2da23c105d8e0b02d54f9f5841013fc81c233010ec781e31f1aee4c/xxhash-4.0.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:81507a68ba84c55241fb61cce1469f473a5da4205fc8ef6f698e5948eea8dd88", size = 339878, upload-time = "2026-08-17T08:35:17.626Z" }, + { url = "https://files.pythonhosted.org/packages/a8/3d/f584cd3172fe934f0f5a0a3917d0d7ce781f74d794fd43bb72be71c3ef6f/xxhash-4.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f1ea31d61bcd2cd2f3ec4ca80a64187bbd7948f490b63cf0dcbc6e717b4c1e9", size = 272871, upload-time = "2026-08-17T08:20:56.067Z" }, + { url = "https://files.pythonhosted.org/packages/34/50/2c7956b2b551682e00b9aebce9ceb0a991a131d65f9850c09f5f9760be2e/xxhash-4.0.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:06713a5aaf1d0905c5579416c020c02e42b3ceb931e86c7d3b7fb85403dee3f3", size = 301440, upload-time = "2026-08-17T08:21:35.911Z" }, + { url = "https://files.pythonhosted.org/packages/eb/a2/0739f6482184a8026f4b022718f5f815d352059312e80696825433f0a8e7/xxhash-4.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e8cda075b10bb3917b002c74a04f9e02b7d13b5bf732571404d51c52b11c7329", size = 260157, upload-time = "2026-08-17T08:22:01.416Z" }, + { url = "https://files.pythonhosted.org/packages/a1/25/b31a7bcf1d7d116842812e54f9b944843b4236ea4fa85634e8259f342212/xxhash-4.0.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c10b9206753b64aa791b35b201485477525b26fdec5bf86e8364c388a03e2592", size = 278233, upload-time = "2026-08-17T08:21:15.674Z" }, + { url = "https://files.pythonhosted.org/packages/db/e8/5293bae090fc6119dbc5fcf5c4cc0e1536394b52d73b7904d033836c73db/xxhash-4.0.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:f3e1a44af01b6692de0ec6caba5f0bf93ceb36896e02b7fc00952c6ea7ef39e1", size = 330270, upload-time = "2026-08-17T08:20:51.128Z" }, + { url = "https://files.pythonhosted.org/packages/72/9e/e2ab12d40921f3f34c9317637d65e011aeababf8288356ea8d527de2c1d0/xxhash-4.0.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:c6fc415b5568bd9accc7187f1729a99707330c0a67a8b9f93c1149ed573ed75d", size = 478555, upload-time = "2026-08-17T08:22:04.183Z" }, + { url = "https://files.pythonhosted.org/packages/6d/32/c6148d39a49efa95f39b4cf0d41ef35a487f3b30f6fb1fc8fe8d8eab577e/xxhash-4.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:96d8de55029d42251945531f6aa7590c32b48163c66a43bf29d8657d7446a377", size = 258174, upload-time = "2026-08-17T08:35:21.18Z" }, + { url = "https://files.pythonhosted.org/packages/8f/fb/0b04b68d6c5bc71c7a2c344f1287327b67e607f28fbcfd937697caca64b6/xxhash-4.0.1-cp312-cp312-pyemscripten_2024_0_wasm32.whl", hash = "sha256:0163b5d259de23ae9e07b7eabf435ce4704f6f205589a2b154e6af4be985ce1b", size = 20767, upload-time = "2026-08-17T08:21:00.806Z" }, + { url = "https://files.pythonhosted.org/packages/a6/be/476092aba34d1fcd313e1613a3bb3bc692f253d167b54bc90049043b5034/xxhash-4.0.1-cp312-cp312-win32.whl", hash = "sha256:1216f7ba5683f17a89eb7dcb4bc50a0b743dfe1902278d7b3d0786f538118433", size = 34669, upload-time = "2026-08-17T08:21:49.486Z" }, + { url = "https://files.pythonhosted.org/packages/aa/02/f9413d94fae43cec6d1a74c4f12156c6f4a7f5fd50e1d34defebdee3dec9/xxhash-4.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:5c2d525a3afabcd8e3549d85fc7e111fde6bc302d06a1893fe73adb79823415e", size = 37073, upload-time = "2026-08-17T08:22:04.886Z" }, + { url = "https://files.pythonhosted.org/packages/c1/83/6fe93c1b95acf962bc61a246df09dc2dcce895ccfc1080c9f48d0b652b92/xxhash-4.0.1-cp312-cp312-win_arm64.whl", hash = "sha256:86b2b12bec60c678ed8f5cca0258ad93a8928ebddb6ca7732f0875afe1451d1a", size = 33299, upload-time = "2026-08-17T08:35:12.708Z" }, + { url = "https://files.pythonhosted.org/packages/f3/dd/c707286b527722f776e1fb81dd202c45623355ba1a2972337a2a26075b2b/xxhash-4.0.1-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:8c9fe122444e129881afd1d4d1c7ac0d3ce2d91b68c2b40173b6025ff1c31f9a", size = 43639, upload-time = "2026-08-17T08:20:54.945Z" }, + { url = "https://files.pythonhosted.org/packages/1b/3b/bb71639a0f95635f61936a6f2653599c4261b645ddddd8d00f9dfe3613e2/xxhash-4.0.1-cp313-cp313-android_24_x86_64.whl", hash = "sha256:1f3346c5c287ac3c7f38b20380f55e8768230e7252af59fabcf3b87ab21e4256", size = 40657, upload-time = "2026-08-17T08:22:12.616Z" }, + { url = "https://files.pythonhosted.org/packages/3c/91/76f3f5385faa9886a36f21fcc603f40b4c0c40ce622382f133160c48b4d9/xxhash-4.0.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:4e5141543c7f7fe3087500bbb4ac2845cb528a980aa91f8f1e661e2292ff4a5d", size = 34708, upload-time = "2026-08-17T08:35:24.614Z" }, + { url = "https://files.pythonhosted.org/packages/9a/4a/f48f0e3e1b1ab072979fff2a5be899234e28090883e8b519d0b10215d708/xxhash-4.0.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:f09ee747e2a5f876cc5ad56947734811828335e13b403dd8ea1e06d77a9dd48d", size = 35650, upload-time = "2026-08-17T08:21:09.337Z" }, + { url = "https://files.pythonhosted.org/packages/c4/53/b73d7472b196101ad1f57ed0674af3af803ac3e9ec2feadd650a7b262562/xxhash-4.0.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:acf52474b2494ef66dc7e0fb6d5e2b50c18313039ad4d275fbf9f9907c804bc5", size = 37958, upload-time = "2026-08-17T08:22:10.616Z" }, + { url = "https://files.pythonhosted.org/packages/d0/f2/024946ad8fa532074af4e4380179da54b7ec9facc8bd0b279ec0fac4e63a/xxhash-4.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1b3cccf75eeb5b01639b2feadb042a8e07889293b7ca72fa2985e7dcb64763cf", size = 38032, upload-time = "2026-08-17T08:22:09.535Z" }, + { url = "https://files.pythonhosted.org/packages/da/e0/934af8d99bb5885711006bec30a691f728edd513d2c40f053f887d8e7577/xxhash-4.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cd878d32f5c6cbce9783f8d6897561fb772211edba9dde49d85672b88ed45276", size = 35895, upload-time = "2026-08-17T08:35:16.53Z" }, + { url = "https://files.pythonhosted.org/packages/20/5f/a8011f6a1558f7ca66d9077bb4f192b1871afcea62fbd5733605d2015755/xxhash-4.0.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:41e579025a6e13a99e6d71e39c9cfc621a0dcdbbf19106325e145fa858f2d794", size = 259464, upload-time = "2026-08-17T08:21:06.72Z" }, + { url = "https://files.pythonhosted.org/packages/ff/89/9665a44397547e7a3d58c0942425a976d58dcfd4b538f33220a312bf6912/xxhash-4.0.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:74379a577a9f3b6afbdedf1b90e5c7764467051977f18a326d7d607336d743bd", size = 283949, upload-time = "2026-08-17T08:22:17.003Z" }, + { url = "https://files.pythonhosted.org/packages/34/2d/78774141266457468f29f3f5803092df4db87d8148ba74e4debd041649db/xxhash-4.0.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:acb31ecdd1a97fab5cd39a84ee9f515e727d319f796fec48703b8339b9998360", size = 303898, upload-time = "2026-08-17T08:35:27.951Z" }, + { url = "https://files.pythonhosted.org/packages/59/48/d78d22de576b42528bff87c14207de50de4f0b888221a50ff7c9d675d670/xxhash-4.0.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5b7875ac1a2edcb691f27642b8b94b904baa6bcecb7d79c72df2228ba8cb5c51", size = 287241, upload-time = "2026-08-17T08:21:13.042Z" }, + { url = "https://files.pythonhosted.org/packages/4c/de/7a1755a59c59fd46176f293bbdd99e399a6537ba9537fc723aa4d1bf6e27/xxhash-4.0.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4751f1d7eecae6b2d2a773630f1a7248f125c9a92a456694d03c15bceffc9d68", size = 519856, upload-time = "2026-08-17T08:22:15.35Z" }, + { url = "https://files.pythonhosted.org/packages/6f/fb/76580c08e916507859b0f335393cb5fdc59452c4402edbc6bcca6e47e7df/xxhash-4.0.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9a51b061d54cda8b83e62c44458bfbf0dabbef9b975dd9649952ba5076b9f349", size = 268572, upload-time = "2026-08-17T08:22:14.533Z" }, + { url = "https://files.pythonhosted.org/packages/d0/2b/1abde3e07b8f2077a38b4fbfaf764115008bfe0ff03bc7756a52c9fd0607/xxhash-4.0.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:74a164e8b63f1e9cf35c9a7809d082b033d1a00e7375d5d814415436e7867e57", size = 344967, upload-time = "2026-08-17T08:35:23.569Z" }, + { url = "https://files.pythonhosted.org/packages/5c/15/80b6ddf0732eef48a8b5fe717398274794392bd6dbe82af38d189d214772/xxhash-4.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f5e5c6df4b703afcbe9352d238a51efd97c3b91fdc3a2052e40fdacb1e7505f", size = 279956, upload-time = "2026-08-17T08:21:24.97Z" }, + { url = "https://files.pythonhosted.org/packages/77/e0/11cbc43c205bf81fad50d69c7319cd1b1ccc01a66cd4fb8766357126c43d/xxhash-4.0.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:d54b8ae068af532c8cdf56abb9e09a60fbe7b10792444c9c27987bb6d3b450fa", size = 307583, upload-time = "2026-08-17T08:22:22.541Z" }, + { url = "https://files.pythonhosted.org/packages/1c/11/cf0bc07feb2791045b6ac075d4bf64f1a5beedef2f46ae70d7104d63a19f/xxhash-4.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1749f0688020209fe0d357ce1e1cd9ec9c6161ed0405ea949d24581c4c43fa91", size = 265848, upload-time = "2026-08-17T08:35:31.298Z" }, + { url = "https://files.pythonhosted.org/packages/d4/c4/7ada4bea2a2795073dfc42d96842930efbe7a0c1857ef4b522e4e90e5d83/xxhash-4.0.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:94ac8a6b8c47951173f0b67bf862bcb971bf24e493b9fbbdb0e010cbbc7d9f54", size = 284409, upload-time = "2026-08-17T08:21:23.156Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f4/d8ce83dd6b99ccfbdadaf2db968ae40334d2e5f73a0297e593b9ddb3df39/xxhash-4.0.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:a33de7633c948ab2dc144af370a66e7e7af29b425dcd0f7e4f59689fb9391b53", size = 335921, upload-time = "2026-08-17T08:22:21.802Z" }, + { url = "https://files.pythonhosted.org/packages/a6/9f/f47d8724bd8bc45b395b06b7cacea2dae0d00031af1b707184a091161df6/xxhash-4.0.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:247ece770647c0aef080561fa996f9774b4dadce2d0c42eeb98229db7dcf820d", size = 487023, upload-time = "2026-08-17T08:22:19.729Z" }, + { url = "https://files.pythonhosted.org/packages/57/54/2d87098f3371cc1e42dd04d2285ad56bca4c56667bc501bff02d2b9fd6b5/xxhash-4.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a4553d36cc0b7fce1f35ba8a94dfd775aa3ed12f5eab2dc3b46ac75a0706b0bb", size = 264333, upload-time = "2026-08-17T08:35:27.001Z" }, + { url = "https://files.pythonhosted.org/packages/27/b8/93795ca5898ec7d7d0455283ad261c0fc76b4f0c0a69e86233bd7badb0bd/xxhash-4.0.1-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:87aa309a93bd5ec13f14309a305ff4e9bf74c5363fc46c264c0a22edfd5b0670", size = 20581, upload-time = "2026-08-17T08:21:39.207Z" }, + { url = "https://files.pythonhosted.org/packages/b6/96/926f7335a0a1647952c00421e8da877f658094f61336306c7cadc335c94d/xxhash-4.0.1-cp313-cp313-win32.whl", hash = "sha256:cba763d84b06bda2c38d5185dee76f1b9dfdc0789e96e476d9e10005526d0788", size = 34449, upload-time = "2026-08-17T08:22:29.362Z" }, + { url = "https://files.pythonhosted.org/packages/ea/61/8a5aeb811de093bab3434e77eff0e9461624a1a56a6a93d315d080aab2aa/xxhash-4.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:97b94fb29abf21f5f0bde15f7dbdd3a4aa2dc59f37026adc7b4bee8563b84375", size = 36520, upload-time = "2026-08-17T08:35:34.852Z" }, + { url = "https://files.pythonhosted.org/packages/04/14/97f3c74000ca36955e9cb86f6d270dcd5848b5c65afa623453f5cf2d83d6/xxhash-4.0.1-cp313-cp313-win_arm64.whl", hash = "sha256:08ed8da18cd4fd0a6a5d6a444852d8fbd0e565388a74a4937085451b5f1a312a", size = 33428, upload-time = "2026-08-17T08:21:31.713Z" }, + { url = "https://files.pythonhosted.org/packages/81/0e/ea406a02b561d3275232ccfdb3e29df80f7a65414940e3a15721c7bea40f/xxhash-4.0.1-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:af05a3f650220a6c59fa0ad2410249f2d2470a05225807c378fb67458693f8df", size = 43747, upload-time = "2026-08-17T08:22:31.37Z" }, + { url = "https://files.pythonhosted.org/packages/f9/f0/b0c94d61ccf6b5d1f8847b58ef8f923125ac4919ed5bd0eb082750ca7cbd/xxhash-4.0.1-cp314-cp314-android_24_x86_64.whl", hash = "sha256:a6e3653df1a70b8ac4191216324242e4be2bca18c9a7c10934e1bd56dc7ca15e", size = 40749, upload-time = "2026-08-17T08:22:29.431Z" }, + { url = "https://files.pythonhosted.org/packages/2f/c5/8085881a538983be0fd1c865d5df236242fea496044e2c8ca32b9f2ba39c/xxhash-4.0.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:4528cf80ebbbf57d40edfb31521ae265daa6dd636d615b1cf0ac86209579e59d", size = 34734, upload-time = "2026-08-17T08:35:33.68Z" }, + { url = "https://files.pythonhosted.org/packages/d3/94/8803d13c968fc75ca434eea991d29ac5fd8a36b4afc9a6a9803c53933db4/xxhash-4.0.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:90cb2a1c9cc503a054a19612b48ff6e8e47805f618bdb3224a07568aad03a37e", size = 35671, upload-time = "2026-08-17T08:21:48.322Z" }, + { url = "https://files.pythonhosted.org/packages/85/d5/ad91d7f0fd294190d37c08236fe661f5c4e3f83dcd1a121877a2e64681ce/xxhash-4.0.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:a949b072ea59c6eca0811ccd9e95133cc50d2afda8d464b5b077c78f78efa269", size = 38094, upload-time = "2026-08-17T08:22:39.763Z" }, + { url = "https://files.pythonhosted.org/packages/89/f4/2b7ebdc1869caca5f02c4cba8379b631050d3c3d4adb9187e4dc1a6b8d3c/xxhash-4.0.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:79a3203aadf39637869dfea1185227d8452844d78b837e54fb1117b4d34ba5c3", size = 38244, upload-time = "2026-08-17T08:35:38.081Z" }, + { url = "https://files.pythonhosted.org/packages/90/9d/f66cf6935f528e575f1ae4d6560d376e7587569747186f4fae8777cadc1b/xxhash-4.0.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d9f3848ffaf010bdbabdbf4c25641fa258b6227ff27bc74a4d06edef521a4873", size = 35904, upload-time = "2026-08-17T08:21:37.358Z" }, + { url = "https://files.pythonhosted.org/packages/07/29/34569d7b482f0dc060074faafd163c588f915cbc3e3e218f1ffd8a3ad340/xxhash-4.0.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9283d9dd6b44acad35118e2976fc763a065509e4118debdb61916ec322ed17b9", size = 259595, upload-time = "2026-08-17T08:22:38.153Z" }, + { url = "https://files.pythonhosted.org/packages/ce/d2/a2370acfcd48732cf5c2b87f06cfbf7fa51c0ce0dd736bde42939eb9ebf7/xxhash-4.0.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c7c642a0f79c3e3cf2965475507574d3d1a50ec71060039d60cb87358667cb2", size = 284279, upload-time = "2026-08-17T08:22:36.396Z" }, + { url = "https://files.pythonhosted.org/packages/08/15/17d33c24e6c4a1c0b9ddc5584f0c25d51d48b34bacde1416a2235a19db4b/xxhash-4.0.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:96dedccfb09a73a25751053a183159b88f4ee75f388df8166040c152ac0531c6", size = 303973, upload-time = "2026-08-17T08:35:39.22Z" }, + { url = "https://files.pythonhosted.org/packages/ec/e0/4ec0d69ad5738729098a61e631b7ed2df22a922b0e03014b597c72bd863d/xxhash-4.0.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81664268dba92e037b740ecf37fa02f1cab4a391f93f28e35792b3341c60648f", size = 287535, upload-time = "2026-08-17T08:21:52.158Z" }, + { url = "https://files.pythonhosted.org/packages/0f/8b/4f9b17e7a9eb71c65548ecddd9c18b84e3c18ca41c4d436ad2a3000d3f7b/xxhash-4.0.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:839f58c5bd9989875be0fd28446dbf32cace2c2cd8bf2f6762acdc38a95cd1aa", size = 519257, upload-time = "2026-08-17T08:22:43.272Z" }, + { url = "https://files.pythonhosted.org/packages/68/35/3276b3e743b8ddbed9c3f71c76d9dd6a75d72aa4e678b1447b635cfd92e0/xxhash-4.0.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ffa44b4c7c5d0ffa31356b4428659516c0e47647825c74079a296b3857b6d99d", size = 268190, upload-time = "2026-08-17T08:35:44.985Z" }, + { url = "https://files.pythonhosted.org/packages/08/d4/f1555de3c96721320930dbb7988c8482d82b85970076aba1a8d40e83ad43/xxhash-4.0.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e681a6fc7e4f715252b9b5acfb30536ec7dd1f75033a32dc617e6fa95af1a3fd", size = 345553, upload-time = "2026-08-17T08:21:41.025Z" }, + { url = "https://files.pythonhosted.org/packages/ac/98/c28908f27007087b61139d290f908dd827ffd40b88af0c43f9e1a1a7ffd5/xxhash-4.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c6301d92545c591ad31c3e050aa40a5f8a4c16413f1f9e6f9322c6f0f9d2b736", size = 280499, upload-time = "2026-08-17T08:22:52.236Z" }, + { url = "https://files.pythonhosted.org/packages/a9/76/3ef57622c65816348f8196273485baab4752aae064959901e85cd867e067/xxhash-4.0.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:6efb8f21cc136c79b3e5bb747c8682d37916fb202cdbbc32182de5c4e47f821f", size = 307211, upload-time = "2026-08-17T08:22:40.815Z" }, + { url = "https://files.pythonhosted.org/packages/8a/4c/5804504bbc808968e57d6a50286dd8f8cc06e0ddd6e4ab4b1dc89ae42f35/xxhash-4.0.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:760de77279e9cf9c81d012ce0705cba13afccee9b09c480f17d778c8c5cefae8", size = 265865, upload-time = "2026-08-17T08:35:42.727Z" }, + { url = "https://files.pythonhosted.org/packages/aa/ee/8572fdfd70e7aaaf150af899871c2cc0bb88c3295ca82172a31e04ca5168/xxhash-4.0.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:a16a3fa6936e36bb1414d16a6bd012c9033e5161b68b426805b61d895392437d", size = 284545, upload-time = "2026-08-17T08:21:56.965Z" }, + { url = "https://files.pythonhosted.org/packages/c1/f8/6eadcca0904660c848b466524e82a233d16c9d2d5258433aaf3546142d86/xxhash-4.0.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:9c3c4b9aa9a27196b921197f7daf9e6c1412739df06a99cfa6e923879362eff6", size = 336022, upload-time = "2026-08-17T08:22:46.346Z" }, + { url = "https://files.pythonhosted.org/packages/27/df/4aa107b81602d6d6d09ab5a607c530d2d3a6b28e2e9a59b01875bd877c54/xxhash-4.0.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:863f3d3b44110f7243e86cf994aa5c5d88f2348b6e84ab4402fadadfbf9f7da7", size = 486671, upload-time = "2026-08-17T08:35:49.016Z" }, + { url = "https://files.pythonhosted.org/packages/45/b7/b2bf9b5301e9cd5f2e335fea8da0f5cf209a6594cb1fe77754774ad4a6fd/xxhash-4.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:63aa52659bc32bb9bd7cb5caf523b4d14429a477762cfac886132d687c1f80fc", size = 263744, upload-time = "2026-08-17T08:21:56.165Z" }, + { url = "https://files.pythonhosted.org/packages/0b/96/35b1c02177ae26234892c2310fb4822ba62411acccbf425ab8f9fd99354a/xxhash-4.0.1-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:67e57b834e07ed973cee7b6da1548ff28a56458d77696fd2a5f397f340694848", size = 20563, upload-time = "2026-08-17T08:35:11.924Z" }, + { url = "https://files.pythonhosted.org/packages/51/c2/a06300b165fbd6b0cb4a9742987f2e997a9f447ce3bf7c6ac97b862ce62a/xxhash-4.0.1-cp314-cp314-win32.whl", hash = "sha256:b6c1f9c59bbe593f88a0aad30be4150f15bd57bd64efb95feeabcb8e563f1ecd", size = 35151, upload-time = "2026-08-17T08:22:44.283Z" }, + { url = "https://files.pythonhosted.org/packages/06/96/c5b37296b78f80fc97124c0fee0c7bbd1bdb6f3b18bcd8748bb113b2d8fc/xxhash-4.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:da544672efd9ad76077928a3e6c5d894e52ce82d3bf14002db4a1bf17d1a36a2", size = 37156, upload-time = "2026-08-17T08:35:46.551Z" }, + { url = "https://files.pythonhosted.org/packages/ce/5e/248f9cd169c2fb62236bedfba246d213bce728f74901e99047e3f3c55875/xxhash-4.0.1-cp314-cp314-win_arm64.whl", hash = "sha256:d0d24a4f3fb63852cd09af46ae4b7a4d00cc8b8615a046dca543786e728d1056", size = 34379, upload-time = "2026-08-17T08:21:59.446Z" }, + { url = "https://files.pythonhosted.org/packages/58/c8/db1d37c0da0324d0298f6abd931ca1d4736e049d9f2081230a8421da74d2/xxhash-4.0.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:349775ac30372b344d2338b2a168c0a1312a644194da25b8bec476d55761a128", size = 38656, upload-time = "2026-08-17T08:22:49.119Z" }, + { url = "https://files.pythonhosted.org/packages/c5/8e/e18998ec465fb977bc74272e5bf3c2e886c13b014cbef916cd607802c709/xxhash-4.0.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:43e5f9169e73d0f0db33b5f6b8554bcce69ac278c966daf83d5eb4eb2f13829f", size = 36306, upload-time = "2026-08-17T08:35:52.853Z" }, + { url = "https://files.pythonhosted.org/packages/ef/1a/b83f86f8a987a3cbcb7e005a6824ff64aecae35abc1395a0d44ee16c3319/xxhash-4.0.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4a252fb862b0ae2590587e625f47a0e03da05cf0205e8830b67b6596c06038b1", size = 273729, upload-time = "2026-08-17T08:21:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/02/4e/2db15aa8508e0cd5b632927a53b98234f24039ea65377e6cf996c06d2d4f/xxhash-4.0.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2df3ca8757dc381e75e90a4d7995a6324f58a923c7145220a7b2c0231f66fddc", size = 301083, upload-time = "2026-08-17T08:35:14.113Z" }, + { url = "https://files.pythonhosted.org/packages/26/94/ed759787ffe802bd8e31cfcdad3755cbeca2dcdafd2f790cd6f25d195199/xxhash-4.0.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:bfed61996d618eb90d6eaae0178002e3466a28b06bfc557a7a3a7266378d8c5a", size = 312745, upload-time = "2026-08-17T08:22:52.232Z" }, + { url = "https://files.pythonhosted.org/packages/45/7a/f64b4a4cc8b51e950709207f55f7f56ae9c5af6631dd31d7fb443312418c/xxhash-4.0.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9761ff4a0ffa583fe850731ad24fe82c88cccb7a2294727db0955f3279a4cb3f", size = 301419, upload-time = "2026-08-17T08:35:50.143Z" }, + { url = "https://files.pythonhosted.org/packages/a0/71/bac313b8de073569b8db3152044a7cfcce87a3fa9698c18fe9f914dee6b1/xxhash-4.0.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:edccc2ec58435a580f96a48a3ccae8cd0a480824119165dd90108718ad81ae6e", size = 534485, upload-time = "2026-08-17T08:22:11.515Z" }, + { url = "https://files.pythonhosted.org/packages/b9/0c/16b5e419f24e59507ee05626d2bb0deafdb03f9f27783bc0785a9849602e/xxhash-4.0.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4741d42d59e4e5fa1a86c17ab9c27dc8ea459c700d91b6742fdb9138d9a516cb", size = 279605, upload-time = "2026-08-17T08:22:52.934Z" }, + { url = "https://files.pythonhosted.org/packages/5f/55/5787dd6e2d8d5b61256a5039f6b18c2193c7c1de4a2fd2413288d0d9c604/xxhash-4.0.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:440c401e146ce64bdb3beb8ff0c84677b6f21307c28a34779071cecee5d4d70c", size = 358924, upload-time = "2026-08-17T08:35:58.164Z" }, + { url = "https://files.pythonhosted.org/packages/f3/68/89be41991f3b0a2e91f940bdf3128852c3ed571cf560d98ad0f67024afe4/xxhash-4.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5b7979f71d06ae45a769de0699900a246d8cb632db1e8bfdc79ec019063a503c", size = 295305, upload-time = "2026-08-17T08:22:13.683Z" }, + { url = "https://files.pythonhosted.org/packages/e6/5a/52ff0a0cc361aad393ff9a46ffe3aabbcf9c03d6c8f2612da7d553048276/xxhash-4.0.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:62198213fc3e0c56e567894b318ba45834e007d065f84ba6dc9165d21546fc56", size = 320228, upload-time = "2026-08-17T08:35:18.946Z" }, + { url = "https://files.pythonhosted.org/packages/0f/b5/91c60ff22c7f6cd5f6d7a5bad5a2cdcb4c33987dfa50bf13f0d856279b2e/xxhash-4.0.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b3bece52127ac20044311ee73567f9f0893b5de64f9028aecc90cc740cfd525a", size = 279414, upload-time = "2026-08-17T08:23:03.212Z" }, + { url = "https://files.pythonhosted.org/packages/b9/94/9685954804d47d0390871a64bec606a0d536406382d71a784df3a5883fb4/xxhash-4.0.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:a865d2d470220e659220fdb59d5b6c4422802d8d6098e1324bc4d12444798914", size = 297594, upload-time = "2026-08-17T08:35:57.881Z" }, + { url = "https://files.pythonhosted.org/packages/89/62/b67ac9412907b7a07a2a0c08c3440b9e4480231a7b3de0767e87011e4564/xxhash-4.0.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8580aab306888224074c7edeec734de0c3c5ccde65b2da4e6c9a5e28f7c0a1bd", size = 348526, upload-time = "2026-08-17T08:22:18.571Z" }, + { url = "https://files.pythonhosted.org/packages/37/ed/6723cc49a9f567d52d01fd7c1741b0f2e3a13e71d15f7ac49d753a20c115/xxhash-4.0.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:2d52dc7c33c1b83082b707f6b7814dc76d2faaa2ea62bd9c5fab4b36f83c087f", size = 499307, upload-time = "2026-08-17T08:22:56.52Z" }, + { url = "https://files.pythonhosted.org/packages/fd/2e/7b10e101ab988d93b791023be7191d7661271d6ab31ac082276b9091042a/xxhash-4.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6a9f98af872355e0c02439e48583958eee00e60b928bb20476460d9d40cb7b4e", size = 274989, upload-time = "2026-08-17T08:36:01.834Z" }, + { url = "https://files.pythonhosted.org/packages/9b/8d/7eabcc8d29cce40621443cff24c07d7306ef574b8956c47ac59f21098005/xxhash-4.0.1-cp314-cp314t-win32.whl", hash = "sha256:a14578102a6081465aec9cf73c76c3cd3f79f0709bdb3b8ae7ab0b54c9d8b089", size = 35482, upload-time = "2026-08-17T08:22:32.336Z" }, + { url = "https://files.pythonhosted.org/packages/ca/89/2a4268e1971f63038b79fb75e3b9c8de942cd77acabbb0c5625352a31940/xxhash-4.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:c57963970d359a72262f7fe6be88f945e2334d4bc41462b7f08c37b0abf35ca6", size = 37490, upload-time = "2026-08-17T08:35:22.475Z" }, + { url = "https://files.pythonhosted.org/packages/90/7b/950ecab1fe4cf421d0a6211ddd9a0ac82e39e55c45a111ceb90953dc6c9a/xxhash-4.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:b659fad79c99b0238c7ad7e9d7dbf4eebfea9097c2dba65fa0a4d18a25b29a2f", size = 34596, upload-time = "2026-08-17T08:23:10.001Z" }, + { url = "https://files.pythonhosted.org/packages/c4/03/7dc3b85fac10751613bfedb0e120734e0e8710054abad3f931e9d3843a14/xxhash-4.0.1-cp315-cp315-android_24_arm64_v8a.whl", hash = "sha256:5adf927dca8c47fde7e683fe69efdd81bc865c4db1fb6bb00b391e2b6185207b", size = 43749, upload-time = "2026-08-17T08:36:00.47Z" }, + { url = "https://files.pythonhosted.org/packages/a5/55/bfac071c5b1c6d6a3d48ab1ab96a15e958a1d7061f4afc97804292d87264/xxhash-4.0.1-cp315-cp315-android_24_x86_64.whl", hash = "sha256:c30dd1af66a820820398b26e0d74e7a9aa43cae705924f23ed828cd8e5c26c3d", size = 40758, upload-time = "2026-08-17T08:22:30.209Z" }, + { url = "https://files.pythonhosted.org/packages/79/87/49a260e685d1a74c56a69432a8ee0527ddcbd684a3c51f87edc3b75639c5/xxhash-4.0.1-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:1bc591533fc975614f7e13594daee76af96b8e1fbcf8de76c8773858fa9e7cea", size = 34788, upload-time = "2026-08-17T08:23:09.014Z" }, + { url = "https://files.pythonhosted.org/packages/6c/ef/50d72ed2170dae872e1c0fe333d0908e0a2afbffe74c5c9037d5406a4b89/xxhash-4.0.1-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:567cbc630302a46a8ecfd943b309ccf5372bb3718f1f3762d452df30f033bcf0", size = 35746, upload-time = "2026-08-17T08:36:05.557Z" }, + { url = "https://files.pythonhosted.org/packages/66/f0/969deaa2bab3bfd5ad5b023442124d2255b9961eef6f797ec74eb8683bdf/xxhash-4.0.1-cp315-cp315-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:e998cb3685b92101ec5de0fb4d9485cf01e50bc418211955c55d98064664cf4c", size = 38098, upload-time = "2026-08-17T08:22:36.906Z" }, + { url = "https://files.pythonhosted.org/packages/86/aa/45ed7d7b8d7b66202a47bf8ff3b77cea28d2ea54dfcdd202b4cfe043e3dc/xxhash-4.0.1-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:c3074db513c81f764053e3da079312ecf85a50d8350c71f4cc0105d9662a9e6c", size = 38251, upload-time = "2026-08-17T08:35:25.774Z" }, + { url = "https://files.pythonhosted.org/packages/f1/9d/45e7520a7856e13800a5dc8cd038d34c6372429465b163af0c5722f16918/xxhash-4.0.1-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:3088dadbffa33c29e0518578430a7dff2e901a212e487aefa5faaa0dc06dad34", size = 35986, upload-time = "2026-08-17T08:23:25.854Z" }, + { url = "https://files.pythonhosted.org/packages/9e/0e/5ad466e5fea18c9f9bdc5828c0506f62190061b4a1b0e688aa54969d0a9e/xxhash-4.0.1-cp315-cp315-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1b50223d92df94d54e1a31469335a2c74b16692e6c1cb726f1e6949514458706", size = 264609, upload-time = "2026-08-17T08:36:04.229Z" }, + { url = "https://files.pythonhosted.org/packages/aa/cf/8f269f85217e3dbd45e31e25e46cc26f3aff0e159ef05d228b4b982c778c/xxhash-4.0.1-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:427b62d62d4f967fbb10b82a3813e4875c2a6e7e7634739f17265b650c7f65a6", size = 285910, upload-time = "2026-08-17T08:22:38.589Z" }, + { url = "https://files.pythonhosted.org/packages/ca/30/2fc1a16ee0f9501d074b798ebfae52e24fa602c7117f5c4b81de71eada72/xxhash-4.0.1-cp315-cp315-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c6370189e8e66b7e608f533b939a9de092ddca6cce084ca0d3d414d2ed5b5d59", size = 306566, upload-time = "2026-08-17T08:23:16.895Z" }, + { url = "https://files.pythonhosted.org/packages/e0/a7/08375cf2b997e1903663fe7525c5973b1987a4f8ad2b8d47463e9143f2ee/xxhash-4.0.1-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ec1a470c6db94ac4589c203921e89ac1bc13e796a8b1784d8135e1893559cd3b", size = 287978, upload-time = "2026-08-17T08:36:09.296Z" }, + { url = "https://files.pythonhosted.org/packages/b2/e5/90a7b404c11add9e53a497d06236152852490c3b2f21e468d97a58f26afe/xxhash-4.0.1-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:37f667dee0f867c42894b34e2a6fe26bf195c0ea4683d9d2b713db023f242c3a", size = 520098, upload-time = "2026-08-17T08:22:41.565Z" }, + { url = "https://files.pythonhosted.org/packages/11/02/7fba10b1b17eb46308f09cc0a4ed513d74dff16b1e22a1c439f011c77129/xxhash-4.0.1-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f18732adcc271741bd651c3e56fa519d8a237d2cccda01fe3afb226bf87f783b", size = 268273, upload-time = "2026-08-17T08:35:29.043Z" }, + { url = "https://files.pythonhosted.org/packages/54/49/c21b228877357a3be43eeeaa22182ad1685796f415390ada475922c084e4/xxhash-4.0.1-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0b42a5a26607e4b2409fea174773a66f2dff9dfdbf2c1a851bb7b804e2c97535", size = 350164, upload-time = "2026-08-17T08:23:29.494Z" }, + { url = "https://files.pythonhosted.org/packages/00/3c/c15bb4aa33d94b78a5553b52e7fa1070565f0199925aeadec3871de20ce9/xxhash-4.0.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:99166cc98637e8bf550cda2aab07f4f1d5f899c45fbd721801aeabcc9d404824", size = 281975, upload-time = "2026-08-17T08:36:08.139Z" }, + { url = "https://files.pythonhosted.org/packages/18/7a/b1d0388315fe7752b7725b68a912667526a1dd48ed492fcc031ac03f4b52/xxhash-4.0.1-cp315-cp315-musllinux_1_2_armv7l.whl", hash = "sha256:6cf633df84d80a1668fcf61e330791dae46825e395549e7d34f376411e75088a", size = 307872, upload-time = "2026-08-17T08:22:42.206Z" }, + { url = "https://files.pythonhosted.org/packages/b4/a1/037cb2dd8cf725c9565dfe3712b2915c0e0276a9154913dbfcbcecbeb672/xxhash-4.0.1-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:e259bb7e1e2d8de6b35f430f5c7220b1c0ebf3962d1ba7ec7545980d5931edb8", size = 268241, upload-time = "2026-08-17T08:23:23.997Z" }, + { url = "https://files.pythonhosted.org/packages/c6/a9/67c44422d0ee082169b238ce24bd2796b82d7c21ed953471365df8c508d8/xxhash-4.0.1-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:704381264b36a18b9c62ecbabe2e71d0fc58c77c129c15355c989b10bf05b6b0", size = 284970, upload-time = "2026-08-17T08:36:13.476Z" }, + { url = "https://files.pythonhosted.org/packages/7f/d0/254a5f51c4014cacc77a26f321372338b924f54e89efb730164ee336d850/xxhash-4.0.1-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:e90b4bcf1d9eb1010fdaee7c9209fb667e74c0684f3ba17f9032bd7319da90c9", size = 338074, upload-time = "2026-08-17T08:22:51.166Z" }, + { url = "https://files.pythonhosted.org/packages/64/03/f21c4830118d72ef3a958ce8bf2152f49e0d4cf200907616c9be6caf372a/xxhash-4.0.1-cp315-cp315-musllinux_1_2_s390x.whl", hash = "sha256:a65785e653573fcd1e33062760ab4c3c3440e8e910765018e4b6ed4ad07b54a0", size = 487626, upload-time = "2026-08-17T08:35:32.768Z" }, + { url = "https://files.pythonhosted.org/packages/45/1f/268a689d741d7da649317eb4ce41760140beb4179aaf43a7216fdbe8100c/xxhash-4.0.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:e3996ff9b6f99180357024336bf5749a8ad6476a9a2523e535c5212b995b12a2", size = 263852, upload-time = "2026-08-17T08:23:41.871Z" }, + { url = "https://files.pythonhosted.org/packages/a7/f5/adaf8101cd7f143191a0b390600294d83924b32cb13770fde8803dce27a2/xxhash-4.0.1-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:99054b838b74d8d3995ea0d410976ae967c46207ae22d6ddfc535e809197dab9", size = 20569, upload-time = "2026-08-17T08:36:11.952Z" }, + { url = "https://files.pythonhosted.org/packages/ee/2c/56a5eb8c993420fc07114c08f447a2b66ee996510b4764cb368b9b44c9f0/xxhash-4.0.1-cp315-cp315-win32.whl", hash = "sha256:6c45258a37fc22721395c09927cb982d3e7a83607cab15be7e2416501bd3a330", size = 35145, upload-time = "2026-08-17T08:22:50.038Z" }, + { url = "https://files.pythonhosted.org/packages/67/c7/65f210db43e62157d0fef3b4d4d7b394821e7733c8bb4ece49f91410a725/xxhash-4.0.1-cp315-cp315-win_amd64.whl", hash = "sha256:0ab851b45c70d4992be7cdeeee16f97a0b677408c758c4b1efb1cfe8030bfd37", size = 37161, upload-time = "2026-08-17T08:23:32.438Z" }, + { url = "https://files.pythonhosted.org/packages/33/ae/1a641d1d60ba219756d9ebe907ff0ecf4445adcf4fa96f6e3da57b91d439/xxhash-4.0.1-cp315-cp315-win_arm64.whl", hash = "sha256:a5b21b42a01a343096a1c018d35e9b7aec9c7065dda53ae8da071e37478b2cea", size = 34378, upload-time = "2026-08-17T08:36:15.912Z" }, + { url = "https://files.pythonhosted.org/packages/48/7f/7698b320b251806d1249e513922a626f19027e104c829a611272250350eb/xxhash-4.0.1-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:44ab12e8cd17d4f001769f00ad465208b4bcb897ed29e65f058f74466b57a98f", size = 38610, upload-time = "2026-08-17T08:22:55.203Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3d/436497e775b647b3b3e9a4ffe8c76c59fa4aa7a9fab6447cb59acf1b50ea/xxhash-4.0.1-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:45e88111ebe331de478ef8d4293efbe88f3cf8b863386c9a2357136b838e1af0", size = 36378, upload-time = "2026-08-17T08:35:36.18Z" }, + { url = "https://files.pythonhosted.org/packages/e3/d8/17a4f8182b9257898aa2a77c2a45f70233eb8e50681a280e8e09d2ee76e9/xxhash-4.0.1-cp315-cp315t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bf430c587f447a554c53768ad76b9846fe7c5632180ef6f69c4fce8b0552fbd0", size = 273559, upload-time = "2026-08-17T08:23:51.075Z" }, + { url = "https://files.pythonhosted.org/packages/83/28/121bd5a5c5adb88e0da772c7bef61964cf9da92956a7a237c7d24c4351b8/xxhash-4.0.1-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:adbd48b30e3f82c89fb2b3e6a87cdd28d113b190a5ed0ee2dee286323ee9a621", size = 299133, upload-time = "2026-08-17T08:36:14.731Z" }, + { url = "https://files.pythonhosted.org/packages/11/8f/57c7b6e04642ed738a0d08a31bed7fc63fdacb661d665f98739cc9751b62/xxhash-4.0.1-cp315-cp315t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e71b34978e77868cbf2d18c5206a4603f9c644dd7181bec5643bd40141d3b8c5", size = 314527, upload-time = "2026-08-17T08:22:54.224Z" }, + { url = "https://files.pythonhosted.org/packages/8e/18/42793917dbab0ea1ff71458aea4875e17a7263f2797b798af048dc81e867/xxhash-4.0.1-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:488ca5c5e28ef56ec4bbb12f835b3f1cbecc5f3510062e70117bc6594851932a", size = 299199, upload-time = "2026-08-17T08:23:36.864Z" }, + { url = "https://files.pythonhosted.org/packages/37/60/51dc92443923d8e908d5614f1145d8d696450f9d6c8f1abe243c6f2a0222/xxhash-4.0.1-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:421b94f3ba7067958d02e38960d987756347aa150df06df11aa68ae1af78c619", size = 531967, upload-time = "2026-08-17T08:36:18.66Z" }, + { url = "https://files.pythonhosted.org/packages/88/c5/d0de77de09661fac71742c4155b1cd65e274f7cc277819d702b6c8ff2db5/xxhash-4.0.1-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f33cf0baa91eccd2cb7b62bf00f10c2264ef578b71dd33a12962e71a36eb4d32", size = 278764, upload-time = "2026-08-17T08:22:58.15Z" }, + { url = "https://files.pythonhosted.org/packages/08/9a/589929c655aba1bfb2c41ee03e50eec1547c39c3042a66bda9c173a9614b/xxhash-4.0.1-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:23a4376b4a3183cb50d4d2a3179f887a7773cc695eb2c908e551bec3221b8c60", size = 359876, upload-time = "2026-08-17T08:35:40.35Z" }, + { url = "https://files.pythonhosted.org/packages/3e/a8/c1d8c94d54d91db2215565f4b4151c1593af3e6d27ac4c00fd1e8d714a02/xxhash-4.0.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:38c3d22129a6958846a3098d68bc8e661704461c0be4793ae28836e4690c8478", size = 293548, upload-time = "2026-08-17T08:23:54.951Z" }, + { url = "https://files.pythonhosted.org/packages/8b/67/85d8abca94508a4dd10561d9dea3e6e68843c6986dd6d9c1b3729c8622e4/xxhash-4.0.1-cp315-cp315t-musllinux_1_2_armv7l.whl", hash = "sha256:87cbdec1a7dd930079671a60b249f3ca4e773e6fbd0676e21e36fdc9dd0f3b00", size = 318780, upload-time = "2026-08-17T08:36:17.623Z" }, + { url = "https://files.pythonhosted.org/packages/1b/16/2b920ed456b9cdcfc99ddc20c3afe42f9f807ee5850773c12fd891f3c08d/xxhash-4.0.1-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:6cbf4e21ef0890804b5bb9ad25c48f9c127758d7f6c66bef374efcacc63c738a", size = 277582, upload-time = "2026-08-17T08:22:57.156Z" }, + { url = "https://files.pythonhosted.org/packages/fa/cc/5811b5997aebb8452047f5800d32fc50eaa29d0ba08d4e426f84450b9c2f/xxhash-4.0.1-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:c101180495cb4ba3617b279a944345c53a5e73b0c150053d1fa8d8af32de9579", size = 295116, upload-time = "2026-08-17T08:23:40.868Z" }, + { url = "https://files.pythonhosted.org/packages/2d/dc/c2f3f9c2f4d6aadb79f17a9f1c9a7ee82638cc873680da044cf29537d2ee/xxhash-4.0.1-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:c0e6ccc2b19ec8a726b2e26062ac71ea63e15500d6bf85910e42481844fdffc1", size = 347065, upload-time = "2026-08-17T08:36:21.618Z" }, + { url = "https://files.pythonhosted.org/packages/a2/4c/750cc642c92252e10772ec09e1a1d995581ba4c3ceb24f6e2d57c7ce47ca/xxhash-4.0.1-cp315-cp315t-musllinux_1_2_s390x.whl", hash = "sha256:8bcba9456242ebf180a04d9443812fd85ffe6bd12bda464dd116fcece8886ff3", size = 497208, upload-time = "2026-08-17T08:23:17.88Z" }, + { url = "https://files.pythonhosted.org/packages/6c/2d/58693cb13d6395f39b6b9bb40c5e0db53a5df7c9fce805aa7e792f64a1a5/xxhash-4.0.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:83b8c2013edb5dc1f9e7268b6496130705bc48d79c86bb8817b3d210b81a5513", size = 274338, upload-time = "2026-08-17T08:35:44.062Z" }, + { url = "https://files.pythonhosted.org/packages/4a/08/9aa9787586d9b3e92d63343ce7dc24f0f445fd9e74ff5d6e85dd82233df5/xxhash-4.0.1-cp315-cp315t-win32.whl", hash = "sha256:aa6ccc7f31018484d652cf52db020003433f3c9fa83189c028bd807d2adde503", size = 35471, upload-time = "2026-08-17T08:24:05.795Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ab/4615789c333bee331ac417885c50105715eeb8244bfc68d2bc37dcfd63ca/xxhash-4.0.1-cp315-cp315t-win_amd64.whl", hash = "sha256:daade8936c4deaaf7b01561324ce438ba4f885d717e9adc62b4d67212ad7d7bd", size = 37488, upload-time = "2026-08-17T08:36:19.929Z" }, + { url = "https://files.pythonhosted.org/packages/fb/81/49f718beb0c55d0411bc4bd90b50a3fbe5863a0e97a2f4d11682ba13d298/xxhash-4.0.1-cp315-cp315t-win_arm64.whl", hash = "sha256:f00330ac7e24769e2032203f2b01794d670916b0c1799fd261340f1af9499875", size = 34590, upload-time = "2026-08-17T08:23:19.597Z" }, + { url = "https://files.pythonhosted.org/packages/86/79/9127ff42a887a348dc4ce3211cf1a962836887adee6f57078132bfba78b4/xxhash-4.0.1-graalpy312-graalpy250_312_native-macosx_10_13_x86_64.whl", hash = "sha256:ff48915bf1871a1f19f74c11834c6329443d306cedc0c05fe7fe617810422a80", size = 31836, upload-time = "2026-08-17T08:36:28.261Z" }, + { url = "https://files.pythonhosted.org/packages/0a/e6/f238693bfdd642adb59c99683964d46d9947fe721ff44d3bd850ae675407/xxhash-4.0.1-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:4a76345f5aceb4ec404918edf9c7f2b5507db864dc0d7455982009ac0890b57b", size = 34453, upload-time = "2026-08-17T08:23:49.795Z" }, + { url = "https://files.pythonhosted.org/packages/40/4b/796ace33cdfb75c91ba6d11615c3bd436355b9f3103e05865bbee9abce57/xxhash-4.0.1-graalpy312-graalpy250_312_native-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:31d86f9e81f3e84e00131ac7c54caf5119ae4ddd82c09c31cff597c813ce1ee2", size = 38488, upload-time = "2026-08-17T08:23:59.901Z" }, + { url = "https://files.pythonhosted.org/packages/ad/23/2d549e5d5d7759eaf9ac2d2d2ab81ff60f1bb2b52cdaae8e5ec5c6524354/xxhash-4.0.1-graalpy312-graalpy250_312_native-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:deca2a30d983d240b8375ec2ee0a4288e72042827fc61df2f7671f8467e4cb2f", size = 38206, upload-time = "2026-08-17T08:36:32.193Z" }, + { url = "https://files.pythonhosted.org/packages/79/98/1ee576b27f78e6107ee4ea8ac03e8a52888dff256e57d560f8282c195563/xxhash-4.0.1-graalpy312-graalpy250_312_native-win_amd64.whl", hash = "sha256:7c343ee174d417a44d0c3355602c0cbbfa52a04d1bbbf1723378c7d2c8f60626", size = 37127, upload-time = "2026-08-17T08:23:42.705Z" }, +] + +[[package]] +name = "zstandard" +version = "0.25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fd/aa/3e0508d5a5dd96529cdc5a97011299056e14c6505b678fd58938792794b1/zstandard-0.25.0.tar.gz", hash = "sha256:7713e1179d162cf5c7906da876ec2ccb9c3a9dcbdffef0cc7f70c3667a205f0b", size = 711513, upload-time = "2025-09-14T22:15:54.002Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/fc/f26eb6ef91ae723a03e16eddb198abcfce2bc5a42e224d44cc8b6765e57e/zstandard-0.25.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7b3c3a3ab9daa3eed242d6ecceead93aebbb8f5f84318d82cee643e019c4b73b", size = 795738, upload-time = "2025-09-14T22:16:56.237Z" }, + { url = "https://files.pythonhosted.org/packages/aa/1c/d920d64b22f8dd028a8b90e2d756e431a5d86194caa78e3819c7bf53b4b3/zstandard-0.25.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:913cbd31a400febff93b564a23e17c3ed2d56c064006f54efec210d586171c00", size = 640436, upload-time = "2025-09-14T22:16:57.774Z" }, + { url = "https://files.pythonhosted.org/packages/53/6c/288c3f0bd9fcfe9ca41e2c2fbfd17b2097f6af57b62a81161941f09afa76/zstandard-0.25.0-cp312-cp312-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:011d388c76b11a0c165374ce660ce2c8efa8e5d87f34996aa80f9c0816698b64", size = 5343019, upload-time = "2025-09-14T22:16:59.302Z" }, + { url = "https://files.pythonhosted.org/packages/1e/15/efef5a2f204a64bdb5571e6161d49f7ef0fffdbca953a615efbec045f60f/zstandard-0.25.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6dffecc361d079bb48d7caef5d673c88c8988d3d33fb74ab95b7ee6da42652ea", size = 5063012, upload-time = "2025-09-14T22:17:01.156Z" }, + { url = "https://files.pythonhosted.org/packages/b7/37/a6ce629ffdb43959e92e87ebdaeebb5ac81c944b6a75c9c47e300f85abdf/zstandard-0.25.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7149623bba7fdf7e7f24312953bcf73cae103db8cae49f8154dd1eadc8a29ecb", size = 5394148, upload-time = "2025-09-14T22:17:03.091Z" }, + { url = "https://files.pythonhosted.org/packages/e3/79/2bf870b3abeb5c070fe2d670a5a8d1057a8270f125ef7676d29ea900f496/zstandard-0.25.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6a573a35693e03cf1d67799fd01b50ff578515a8aeadd4595d2a7fa9f3ec002a", size = 5451652, upload-time = "2025-09-14T22:17:04.979Z" }, + { url = "https://files.pythonhosted.org/packages/53/60/7be26e610767316c028a2cbedb9a3beabdbe33e2182c373f71a1c0b88f36/zstandard-0.25.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5a56ba0db2d244117ed744dfa8f6f5b366e14148e00de44723413b2f3938a902", size = 5546993, upload-time = "2025-09-14T22:17:06.781Z" }, + { url = "https://files.pythonhosted.org/packages/85/c7/3483ad9ff0662623f3648479b0380d2de5510abf00990468c286c6b04017/zstandard-0.25.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:10ef2a79ab8e2974e2075fb984e5b9806c64134810fac21576f0668e7ea19f8f", size = 5046806, upload-time = "2025-09-14T22:17:08.415Z" }, + { url = "https://files.pythonhosted.org/packages/08/b3/206883dd25b8d1591a1caa44b54c2aad84badccf2f1de9e2d60a446f9a25/zstandard-0.25.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aaf21ba8fb76d102b696781bddaa0954b782536446083ae3fdaa6f16b25a1c4b", size = 5576659, upload-time = "2025-09-14T22:17:10.164Z" }, + { url = "https://files.pythonhosted.org/packages/9d/31/76c0779101453e6c117b0ff22565865c54f48f8bd807df2b00c2c404b8e0/zstandard-0.25.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1869da9571d5e94a85a5e8d57e4e8807b175c9e4a6294e3b66fa4efb074d90f6", size = 4953933, upload-time = "2025-09-14T22:17:11.857Z" }, + { url = "https://files.pythonhosted.org/packages/18/e1/97680c664a1bf9a247a280a053d98e251424af51f1b196c6d52f117c9720/zstandard-0.25.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:809c5bcb2c67cd0ed81e9229d227d4ca28f82d0f778fc5fea624a9def3963f91", size = 5268008, upload-time = "2025-09-14T22:17:13.627Z" }, + { url = "https://files.pythonhosted.org/packages/1e/73/316e4010de585ac798e154e88fd81bb16afc5c5cb1a72eeb16dd37e8024a/zstandard-0.25.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f27662e4f7dbf9f9c12391cb37b4c4c3cb90ffbd3b1fb9284dadbbb8935fa708", size = 5433517, upload-time = "2025-09-14T22:17:16.103Z" }, + { url = "https://files.pythonhosted.org/packages/5b/60/dd0f8cfa8129c5a0ce3ea6b7f70be5b33d2618013a161e1ff26c2b39787c/zstandard-0.25.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:99c0c846e6e61718715a3c9437ccc625de26593fea60189567f0118dc9db7512", size = 5814292, upload-time = "2025-09-14T22:17:17.827Z" }, + { url = "https://files.pythonhosted.org/packages/fc/5f/75aafd4b9d11b5407b641b8e41a57864097663699f23e9ad4dbb91dc6bfe/zstandard-0.25.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:474d2596a2dbc241a556e965fb76002c1ce655445e4e3bf38e5477d413165ffa", size = 5360237, upload-time = "2025-09-14T22:17:19.954Z" }, + { url = "https://files.pythonhosted.org/packages/ff/8d/0309daffea4fcac7981021dbf21cdb2e3427a9e76bafbcdbdf5392ff99a4/zstandard-0.25.0-cp312-cp312-win32.whl", hash = "sha256:23ebc8f17a03133b4426bcc04aabd68f8236eb78c3760f12783385171b0fd8bd", size = 436922, upload-time = "2025-09-14T22:17:24.398Z" }, + { url = "https://files.pythonhosted.org/packages/79/3b/fa54d9015f945330510cb5d0b0501e8253c127cca7ebe8ba46a965df18c5/zstandard-0.25.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffef5a74088f1e09947aecf91011136665152e0b4b359c42be3373897fb39b01", size = 506276, upload-time = "2025-09-14T22:17:21.429Z" }, + { url = "https://files.pythonhosted.org/packages/ea/6b/8b51697e5319b1f9ac71087b0af9a40d8a6288ff8025c36486e0c12abcc4/zstandard-0.25.0-cp312-cp312-win_arm64.whl", hash = "sha256:181eb40e0b6a29b3cd2849f825e0fa34397f649170673d385f3598ae17cca2e9", size = 462679, upload-time = "2025-09-14T22:17:23.147Z" }, + { url = "https://files.pythonhosted.org/packages/35/0b/8df9c4ad06af91d39e94fa96cc010a24ac4ef1378d3efab9223cc8593d40/zstandard-0.25.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec996f12524f88e151c339688c3897194821d7f03081ab35d31d1e12ec975e94", size = 795735, upload-time = "2025-09-14T22:17:26.042Z" }, + { url = "https://files.pythonhosted.org/packages/3f/06/9ae96a3e5dcfd119377ba33d4c42a7d89da1efabd5cb3e366b156c45ff4d/zstandard-0.25.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a1a4ae2dec3993a32247995bdfe367fc3266da832d82f8438c8570f989753de1", size = 640440, upload-time = "2025-09-14T22:17:27.366Z" }, + { url = "https://files.pythonhosted.org/packages/d9/14/933d27204c2bd404229c69f445862454dcc101cd69ef8c6068f15aaec12c/zstandard-0.25.0-cp313-cp313-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:e96594a5537722fdfb79951672a2a63aec5ebfb823e7560586f7484819f2a08f", size = 5343070, upload-time = "2025-09-14T22:17:28.896Z" }, + { url = "https://files.pythonhosted.org/packages/6d/db/ddb11011826ed7db9d0e485d13df79b58586bfdec56e5c84a928a9a78c1c/zstandard-0.25.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bfc4e20784722098822e3eee42b8e576b379ed72cca4a7cb856ae733e62192ea", size = 5063001, upload-time = "2025-09-14T22:17:31.044Z" }, + { url = "https://files.pythonhosted.org/packages/db/00/87466ea3f99599d02a5238498b87bf84a6348290c19571051839ca943777/zstandard-0.25.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:457ed498fc58cdc12fc48f7950e02740d4f7ae9493dd4ab2168a47c93c31298e", size = 5394120, upload-time = "2025-09-14T22:17:32.711Z" }, + { url = "https://files.pythonhosted.org/packages/2b/95/fc5531d9c618a679a20ff6c29e2b3ef1d1f4ad66c5e161ae6ff847d102a9/zstandard-0.25.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:fd7a5004eb1980d3cefe26b2685bcb0b17989901a70a1040d1ac86f1d898c551", size = 5451230, upload-time = "2025-09-14T22:17:34.41Z" }, + { url = "https://files.pythonhosted.org/packages/63/4b/e3678b4e776db00f9f7b2fe58e547e8928ef32727d7a1ff01dea010f3f13/zstandard-0.25.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8e735494da3db08694d26480f1493ad2cf86e99bdd53e8e9771b2752a5c0246a", size = 5547173, upload-time = "2025-09-14T22:17:36.084Z" }, + { url = "https://files.pythonhosted.org/packages/4e/d5/ba05ed95c6b8ec30bd468dfeab20589f2cf709b5c940483e31d991f2ca58/zstandard-0.25.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3a39c94ad7866160a4a46d772e43311a743c316942037671beb264e395bdd611", size = 5046736, upload-time = "2025-09-14T22:17:37.891Z" }, + { url = "https://files.pythonhosted.org/packages/50/d5/870aa06b3a76c73eced65c044b92286a3c4e00554005ff51962deef28e28/zstandard-0.25.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:172de1f06947577d3a3005416977cce6168f2261284c02080e7ad0185faeced3", size = 5576368, upload-time = "2025-09-14T22:17:40.206Z" }, + { url = "https://files.pythonhosted.org/packages/5d/35/398dc2ffc89d304d59bc12f0fdd931b4ce455bddf7038a0a67733a25f550/zstandard-0.25.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3c83b0188c852a47cd13ef3bf9209fb0a77fa5374958b8c53aaa699398c6bd7b", size = 4954022, upload-time = "2025-09-14T22:17:41.879Z" }, + { url = "https://files.pythonhosted.org/packages/9a/5c/36ba1e5507d56d2213202ec2b05e8541734af5f2ce378c5d1ceaf4d88dc4/zstandard-0.25.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1673b7199bbe763365b81a4f3252b8e80f44c9e323fc42940dc8843bfeaf9851", size = 5267889, upload-time = "2025-09-14T22:17:43.577Z" }, + { url = "https://files.pythonhosted.org/packages/70/e8/2ec6b6fb7358b2ec0113ae202647ca7c0e9d15b61c005ae5225ad0995df5/zstandard-0.25.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0be7622c37c183406f3dbf0cba104118eb16a4ea7359eeb5752f0794882fc250", size = 5433952, upload-time = "2025-09-14T22:17:45.271Z" }, + { url = "https://files.pythonhosted.org/packages/7b/01/b5f4d4dbc59ef193e870495c6f1275f5b2928e01ff5a81fecb22a06e22fb/zstandard-0.25.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:5f5e4c2a23ca271c218ac025bd7d635597048b366d6f31f420aaeb715239fc98", size = 5814054, upload-time = "2025-09-14T22:17:47.08Z" }, + { url = "https://files.pythonhosted.org/packages/b2/e5/fbd822d5c6f427cf158316d012c5a12f233473c2f9c5fe5ab1ae5d21f3d8/zstandard-0.25.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f187a0bb61b35119d1926aee039524d1f93aaf38a9916b8c4b78ac8514a0aaf", size = 5360113, upload-time = "2025-09-14T22:17:48.893Z" }, + { url = "https://files.pythonhosted.org/packages/8e/e0/69a553d2047f9a2c7347caa225bb3a63b6d7704ad74610cb7823baa08ed7/zstandard-0.25.0-cp313-cp313-win32.whl", hash = "sha256:7030defa83eef3e51ff26f0b7bfb229f0204b66fe18e04359ce3474ac33cbc09", size = 436936, upload-time = "2025-09-14T22:17:52.658Z" }, + { url = "https://files.pythonhosted.org/packages/d9/82/b9c06c870f3bd8767c201f1edbdf9e8dc34be5b0fbc5682c4f80fe948475/zstandard-0.25.0-cp313-cp313-win_amd64.whl", hash = "sha256:1f830a0dac88719af0ae43b8b2d6aef487d437036468ef3c2ea59c51f9d55fd5", size = 506232, upload-time = "2025-09-14T22:17:50.402Z" }, + { url = "https://files.pythonhosted.org/packages/d4/57/60c3c01243bb81d381c9916e2a6d9e149ab8627c0c7d7abb2d73384b3c0c/zstandard-0.25.0-cp313-cp313-win_arm64.whl", hash = "sha256:85304a43f4d513f5464ceb938aa02c1e78c2943b29f44a750b48b25ac999a049", size = 462671, upload-time = "2025-09-14T22:17:51.533Z" }, + { url = "https://files.pythonhosted.org/packages/3d/5c/f8923b595b55fe49e30612987ad8bf053aef555c14f05bb659dd5dbe3e8a/zstandard-0.25.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e29f0cf06974c899b2c188ef7f783607dbef36da4c242eb6c82dcd8b512855e3", size = 795887, upload-time = "2025-09-14T22:17:54.198Z" }, + { url = "https://files.pythonhosted.org/packages/8d/09/d0a2a14fc3439c5f874042dca72a79c70a532090b7ba0003be73fee37ae2/zstandard-0.25.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:05df5136bc5a011f33cd25bc9f506e7426c0c9b3f9954f056831ce68f3b6689f", size = 640658, upload-time = "2025-09-14T22:17:55.423Z" }, + { url = "https://files.pythonhosted.org/packages/5d/7c/8b6b71b1ddd517f68ffb55e10834388d4f793c49c6b83effaaa05785b0b4/zstandard-0.25.0-cp314-cp314-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:f604efd28f239cc21b3adb53eb061e2a205dc164be408e553b41ba2ffe0ca15c", size = 5379849, upload-time = "2025-09-14T22:17:57.372Z" }, + { url = "https://files.pythonhosted.org/packages/a4/86/a48e56320d0a17189ab7a42645387334fba2200e904ee47fc5a26c1fd8ca/zstandard-0.25.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223415140608d0f0da010499eaa8ccdb9af210a543fac54bce15babbcfc78439", size = 5058095, upload-time = "2025-09-14T22:17:59.498Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ad/eb659984ee2c0a779f9d06dbfe45e2dc39d99ff40a319895df2d3d9a48e5/zstandard-0.25.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e54296a283f3ab5a26fc9b8b5d4978ea0532f37b231644f367aa588930aa043", size = 5551751, upload-time = "2025-09-14T22:18:01.618Z" }, + { url = "https://files.pythonhosted.org/packages/61/b3/b637faea43677eb7bd42ab204dfb7053bd5c4582bfe6b1baefa80ac0c47b/zstandard-0.25.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ca54090275939dc8ec5dea2d2afb400e0f83444b2fc24e07df7fdef677110859", size = 6364818, upload-time = "2025-09-14T22:18:03.769Z" }, + { url = "https://files.pythonhosted.org/packages/31/dc/cc50210e11e465c975462439a492516a73300ab8caa8f5e0902544fd748b/zstandard-0.25.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e09bb6252b6476d8d56100e8147b803befa9a12cea144bbe629dd508800d1ad0", size = 5560402, upload-time = "2025-09-14T22:18:05.954Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ae/56523ae9c142f0c08efd5e868a6da613ae76614eca1305259c3bf6a0ed43/zstandard-0.25.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a9ec8c642d1ec73287ae3e726792dd86c96f5681eb8df274a757bf62b750eae7", size = 4955108, upload-time = "2025-09-14T22:18:07.68Z" }, + { url = "https://files.pythonhosted.org/packages/98/cf/c899f2d6df0840d5e384cf4c4121458c72802e8bda19691f3b16619f51e9/zstandard-0.25.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a4089a10e598eae6393756b036e0f419e8c1d60f44a831520f9af41c14216cf2", size = 5269248, upload-time = "2025-09-14T22:18:09.753Z" }, + { url = "https://files.pythonhosted.org/packages/1b/c0/59e912a531d91e1c192d3085fc0f6fb2852753c301a812d856d857ea03c6/zstandard-0.25.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f67e8f1a324a900e75b5e28ffb152bcac9fbed1cc7b43f99cd90f395c4375344", size = 5430330, upload-time = "2025-09-14T22:18:11.966Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/7e31db1240de2df22a58e2ea9a93fc6e38cc29353e660c0272b6735d6669/zstandard-0.25.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:9654dbc012d8b06fc3d19cc825af3f7bf8ae242226df5f83936cb39f5fdc846c", size = 5811123, upload-time = "2025-09-14T22:18:13.907Z" }, + { url = "https://files.pythonhosted.org/packages/f6/49/fac46df5ad353d50535e118d6983069df68ca5908d4d65b8c466150a4ff1/zstandard-0.25.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4203ce3b31aec23012d3a4cf4a2ed64d12fea5269c49aed5e4c3611b938e4088", size = 5359591, upload-time = "2025-09-14T22:18:16.465Z" }, + { url = "https://files.pythonhosted.org/packages/c2/38/f249a2050ad1eea0bb364046153942e34abba95dd5520af199aed86fbb49/zstandard-0.25.0-cp314-cp314-win32.whl", hash = "sha256:da469dc041701583e34de852d8634703550348d5822e66a0c827d39b05365b12", size = 444513, upload-time = "2025-09-14T22:18:20.61Z" }, + { url = "https://files.pythonhosted.org/packages/3a/43/241f9615bcf8ba8903b3f0432da069e857fc4fd1783bd26183db53c4804b/zstandard-0.25.0-cp314-cp314-win_amd64.whl", hash = "sha256:c19bcdd826e95671065f8692b5a4aa95c52dc7a02a4c5a0cac46deb879a017a2", size = 516118, upload-time = "2025-09-14T22:18:17.849Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ef/da163ce2450ed4febf6467d77ccb4cd52c4c30ab45624bad26ca0a27260c/zstandard-0.25.0-cp314-cp314-win_arm64.whl", hash = "sha256:d7541afd73985c630bafcd6338d2518ae96060075f9463d7dc14cfb33514383d", size = 476940, upload-time = "2025-09-14T22:18:19.088Z" }, +]