Skip to content

Commit cb8e15b

Browse files
Pigbibicodex
andcommitted
refactor: isolate strategy spec validation
Co-Authored-By: Codex <noreply@openai.com>
1 parent f59c18b commit cb8e15b

9 files changed

Lines changed: 38 additions & 10 deletions

File tree

docs/quant_strategy_spec_contract.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ quant-strategy-spec path/to/spec.json
3030
The command is silent on success, prints field-level contract violations to
3131
stderr on failure, and returns a non-zero exit code. Code integrations may
3232
use `validate_research_spec`, `validate_optimization_spec`, or
33-
`validate_strategy_spec_file` from `quant_platform_kit.strategy_lifecycle`.
33+
`validate_strategy_spec_file` from the lightweight
34+
`quant_platform_kit.strategy_spec` package.
3435
Source checkouts may use `python scripts/validate_strategy_spec.py` as an
3536
equivalent compatibility wrapper.
3637

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ dependencies = []
1616

1717
[project.scripts]
1818
quant-lifecycle = "quant_platform_kit.strategy_lifecycle.cli:main"
19-
quant-strategy-spec = "quant_platform_kit.strategy_lifecycle.spec_cli:main"
19+
quant-strategy-spec = "quant_platform_kit.strategy_spec.cli:main"
2020

2121
[tool.setuptools]
2222
package-dir = { "" = "src" }

scripts/validate_strategy_spec.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
ROOT = Path(__file__).resolve().parents[1]
1111
sys.path.insert(0, str(ROOT / "src"))
1212

13-
from quant_platform_kit.strategy_lifecycle.spec_cli import main
13+
from quant_platform_kit.strategy_spec.cli import main
1414

1515

1616
if __name__ == "__main__":

src/quant_platform_kit.egg-info/SOURCES.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,12 @@ src/quant_platform_kit/strategy_lifecycle/performance_store.py
139139
src/quant_platform_kit/strategy_lifecycle/return_collector.py
140140
src/quant_platform_kit/strategy_lifecycle/rollback_manager.py
141141
src/quant_platform_kit/strategy_lifecycle/shadow_validator.py
142-
src/quant_platform_kit/strategy_lifecycle/spec_cli.py
143-
src/quant_platform_kit/strategy_lifecycle/spec_validation.py
144142
src/quant_platform_kit/strategy_lifecycle/strategy_health_score.py
145143
src/quant_platform_kit/strategy_lifecycle/update_orchestrator.py
146144
src/quant_platform_kit/strategy_lifecycle/update_policy.py
145+
src/quant_platform_kit/strategy_spec/__init__.py
146+
src/quant_platform_kit/strategy_spec/cli.py
147+
src/quant_platform_kit/strategy_spec/validation.py
147148
tests/test_backtest_orchestrator.py
148149
tests/test_binance_account.py
149150
tests/test_binance_client.py

src/quant_platform_kit/strategy_lifecycle/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
UpdateStage,
1515
WindowPerformance,
1616
)
17-
from quant_platform_kit.strategy_lifecycle.spec_validation import (
17+
from quant_platform_kit.strategy_spec import (
1818
OPTIMIZATION_SPEC_SCHEMA_VERSION,
1919
RESEARCH_SPEC_SCHEMA_VERSION,
2020
validate_optimization_spec,
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""Lightweight public API for versioned strategy specification contracts."""
2+
3+
from quant_platform_kit.strategy_spec.validation import (
4+
OPTIMIZATION_SPEC_SCHEMA_VERSION,
5+
RESEARCH_SPEC_SCHEMA_VERSION,
6+
validate_optimization_spec,
7+
validate_research_spec,
8+
validate_strategy_spec,
9+
validate_strategy_spec_file,
10+
)
11+
12+
__all__ = [
13+
"OPTIMIZATION_SPEC_SCHEMA_VERSION",
14+
"RESEARCH_SPEC_SCHEMA_VERSION",
15+
"validate_optimization_spec",
16+
"validate_research_spec",
17+
"validate_strategy_spec",
18+
"validate_strategy_spec_file",
19+
]

src/quant_platform_kit/strategy_lifecycle/spec_cli.py renamed to src/quant_platform_kit/strategy_spec/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import argparse
66
import sys
77

8-
from quant_platform_kit.strategy_lifecycle.spec_validation import validate_strategy_spec_file
8+
from quant_platform_kit.strategy_spec.validation import validate_strategy_spec_file
99

1010

1111
def main(argv: list[str] | None = None) -> int:

src/quant_platform_kit/strategy_lifecycle/spec_validation.py renamed to src/quant_platform_kit/strategy_spec/validation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ def _parse_date(value: Any) -> date | None:
443443

444444

445445
def _parse_datetime(value: str) -> datetime | None:
446-
candidate = value.strip()
446+
candidate = value
447447
if not _RFC3339_DATETIME.fullmatch(candidate):
448448
return None
449449
if candidate.endswith("Z"):

tests/test_strategy_spec_validation.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
import sys
77
from pathlib import Path
88

9-
from quant_platform_kit.strategy_lifecycle.spec_validation import (
9+
from quant_platform_kit.strategy_spec import (
1010
OPTIMIZATION_SPEC_SCHEMA_VERSION,
1111
RESEARCH_SPEC_SCHEMA_VERSION,
1212
validate_optimization_spec,
1313
validate_research_spec,
1414
validate_strategy_spec_file,
1515
)
16-
from quant_platform_kit.strategy_lifecycle.spec_cli import main as spec_cli_main
16+
from quant_platform_kit.strategy_spec.cli import main as spec_cli_main
1717

1818

1919
ROOT = Path(__file__).resolve().parents[1]
@@ -196,6 +196,13 @@ def test_research_spec_rejects_naive_or_date_only_timestamps() -> None:
196196
assert "data.as_of must be an ISO date-time" in issues
197197

198198

199+
def test_research_spec_rejects_timestamp_whitespace() -> None:
200+
payload = _research_spec()
201+
payload["created_at"] = " 2026-07-11T00:00:00Z "
202+
203+
assert "created_at must be an ISO date-time" in validate_research_spec(payload)
204+
205+
199206
def test_research_spec_rejects_non_rfc3339_date_forms() -> None:
200207
payload = _research_spec()
201208
evaluation = payload["evaluation"]

0 commit comments

Comments
 (0)