From 1e9a63d1a25d6483a74d17eb5d6c99ff353998fd Mon Sep 17 00:00:00 2001 From: Pigbibi <20649888+Pigbibi@users.noreply.github.com> Date: Fri, 18 Sep 2026 04:22:09 +0800 Subject: [PATCH] feat(receipts): accept no_signal and no_rebalance outcomes Align the execution_receipts closed set with QRT consumers so no-trade receipts can be built and validated without changing platform producers. Co-authored-by: Cursor --- src/quant_platform_kit/common/execution_receipts.py | 4 ++++ tests/test_execution_receipts.py | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/quant_platform_kit/common/execution_receipts.py b/src/quant_platform_kit/common/execution_receipts.py index 84d3aee..fdac6e2 100644 --- a/src/quant_platform_kit/common/execution_receipts.py +++ b/src/quant_platform_kit/common/execution_receipts.py @@ -36,6 +36,8 @@ { "not_due", "no_action", + "no_signal", + "no_rebalance", "risk_blocked", "submitted", "broker_acknowledged", @@ -58,6 +60,8 @@ _OUTCOME_CONFIRMATIONS = { "not_due": frozenset({"not_applicable"}), "no_action": frozenset({"not_applicable"}), + "no_signal": frozenset({"not_applicable"}), + "no_rebalance": frozenset({"not_applicable"}), "risk_blocked": frozenset({"not_applicable"}), "submitted": frozenset({"not_observed"}), "broker_acknowledged": frozenset({"acknowledged"}), diff --git a/tests/test_execution_receipts.py b/tests/test_execution_receipts.py index cb7d37e..e4537d2 100644 --- a/tests/test_execution_receipts.py +++ b/tests/test_execution_receipts.py @@ -74,6 +74,17 @@ def test_failed_outcome_requires_an_explicit_non_claiming_confirmation(self) -> receipt = _receipt(outcome="failed", broker_confirmation="not_observed") self.assertEqual(receipt["broker_confirmation"], "not_observed") + def test_accepts_no_signal_and_no_rebalance_with_default_confirmation(self) -> None: + for outcome in ("no_signal", "no_rebalance"): + with self.subTest(outcome=outcome): + receipt = _receipt(outcome=outcome) + self.assertEqual(receipt["outcome"], outcome) + self.assertEqual(receipt["broker_confirmation"], "not_applicable") + self.assertEqual(validate_execution_receipt(receipt), receipt) + + with self.assertRaisesRegex(ValueError, "broker_confirmation"): + _receipt(outcome=outcome, broker_confirmation="filled") + def test_rejects_tampered_or_inconsistent_receipts(self) -> None: receipt = _receipt() tampered = copy.deepcopy(receipt)