From 3e9a4efcc20dd361195048a91a29e5da021c4bd9 Mon Sep 17 00:00:00 2001 From: AdrianoDev Date: Mon, 11 May 2026 16:56:36 +0200 Subject: [PATCH] feat(protocol): extend KNOWN_FEATURES with temporal feature names --- src/multi_swarm/protocol/grammar.py | 3 ++- tests/unit/test_protocol_validator.py | 30 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/multi_swarm/protocol/grammar.py b/src/multi_swarm/protocol/grammar.py index 52ff752..657988b 100644 --- a/src/multi_swarm/protocol/grammar.py +++ b/src/multi_swarm/protocol/grammar.py @@ -20,7 +20,8 @@ KNOWN_INDICATORS: frozenset[str] = frozenset( {"sma", "rsi", "atr", "macd", "realized_vol"} ) KNOWN_FEATURES: frozenset[str] = frozenset( - {"open", "high", "low", "close", "volume"} + {"open", "high", "low", "close", "volume", + "hour", "dow", "is_weekend", "minute_of_hour"} ) # Convenience union (utile a validator / parser). diff --git a/tests/unit/test_protocol_validator.py b/tests/unit/test_protocol_validator.py index 472b885..d402433 100644 --- a/tests/unit/test_protocol_validator.py +++ b/tests/unit/test_protocol_validator.py @@ -151,3 +151,33 @@ def test_feature_unknown_column_fails() -> None: ast = parse_strategy(src) with pytest.raises(ValidationError, match="unknown feature"): validate_strategy(ast) + + +def test_validator_accepts_temporal_features() -> None: + for name in ("hour", "dow", "is_weekend", "minute_of_hour"): + src = _wrap( + { + "op": "gt", + "args": [ + {"kind": "feature", "name": name}, + {"kind": "literal", "value": 0}, + ], + } + ) + ast = parse_strategy(src) + validate_strategy(ast) # no exception + + +def test_validator_rejects_temporal_typo() -> None: + src = _wrap( + { + "op": "gt", + "args": [ + {"kind": "feature", "name": "weekday"}, + {"kind": "literal", "value": 0}, + ], + } + ) + ast = parse_strategy(src) + with pytest.raises(ValidationError, match="unknown feature"): + validate_strategy(ast)