Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions application/execution_receipt_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@
_RISK_BLOCKED_STAGES = frozenset({"EXECUTION_BLOCKED", "FUNDING_BLOCKED"})


def _is_legacy_unattested(report: Mapping[str, Any]) -> bool:
receipt = report.get("runtime_release_receipt")
return (
isinstance(receipt, Mapping)
and receipt.get("attestation_state") == "legacy_unattested"
and receipt.get("strategy_release") is None
)


def attach_strategy_result_execution_receipt(
report: dict[str, Any],
result: Mapping[str, Any],
Expand All @@ -28,6 +37,9 @@ def attach_strategy_result_execution_receipt(
never infers an acknowledgement or fill from it.
"""

if _is_legacy_unattested(report):
return report

stage = str(result.get("strategy_run_stage") or "").strip().upper()
submitted_orders = _as_sequence(result.get("submitted_orders"))
submission_attempted = bool(
Expand Down Expand Up @@ -67,6 +79,9 @@ def attach_strategy_result_execution_receipt(
def attach_unknown_failure_execution_receipt(report: dict[str, Any]) -> dict[str, Any]:
"""Preserve uncertainty when an exception escapes the strategy cycle."""

if _is_legacy_unattested(report):
return report

outcome, confirmation = resolve_execution_receipt_fact(
dry_run=bool(report.get("dry_run")),
submission_attempted=True,
Expand Down
6 changes: 5 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,11 @@ def _runtime_settings(*, dry_run_override: bool | None = None) -> PlatformRuntim
return settings
runtime_target = settings.runtime_target
if runtime_target is not None:
runtime_target = replace(runtime_target, dry_run_only=bool(dry_run_override))
runtime_target = replace(
runtime_target,
dry_run_only=bool(dry_run_override),
execution_environment="dry_run" if dry_run_override else runtime_target.execution_environment,
)
return replace(
settings,
dry_run_only=bool(dry_run_override),
Expand Down
32 changes: 31 additions & 1 deletion tests/test_execution_receipt_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import unittest

from application.execution_receipt_adapter import attach_strategy_result_execution_receipt
from application.execution_receipt_adapter import (
attach_strategy_result_execution_receipt,
attach_unknown_failure_execution_receipt,
)


REVISION = "a" * 40
Expand All @@ -22,6 +25,33 @@ def _report() -> dict[str, object]:


class ExecutionReceiptAdapterTest(unittest.TestCase):
def test_legacy_unattested_results_do_not_fabricate_receipts(self) -> None:
for attach in (
lambda report: attach_strategy_result_execution_receipt(report, {}, dry_run=False),
attach_unknown_failure_execution_receipt,
):
report = _report()
report["runtime_release_receipt"] = {"attestation_state": "legacy_unattested"}
self.assertIs(attach(report), report)
self.assertNotIn("execution_receipt", report)

def test_invalid_attested_revision_still_fails(self) -> None:
for revision in (None, "abc1234", "A" * 40):
for attach in (
lambda report: attach_strategy_result_execution_receipt(report, {}, dry_run=False),
attach_unknown_failure_execution_receipt,
):
report = _report()
report["runtime_release_receipt"]["strategy_release"]["strategy_revision"] = revision
with self.assertRaisesRegex(ValueError, "strategy_revision"):
attach(report)

def test_missing_attestation_is_not_assumed_legacy(self) -> None:
report = _report()
del report["runtime_release_receipt"]
with self.assertRaisesRegex(ValueError, "strategy_revision"):
attach_unknown_failure_execution_receipt(report)

def test_submission_is_not_reported_as_a_fill(self) -> None:
report = _report()

Expand Down
43 changes: 43 additions & 0 deletions tests/test_request_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,49 @@ def route_methods():
return {route: sorted(methods) for route, methods in methods_by_route.items()}


@pytest.mark.parametrize("dry_run", [False, True])
@pytest.mark.parametrize("outcome", ["submitted", "blocked", "exception"])
def test_legacy_cycle_preserves_result_and_report(monkeypatch, dry_run, outcome):
persisted = []
cycle_calls = []
failure = RuntimeError("offline strategy failure")
result = {
"ok": outcome == "submitted",
"strategy_run_stage": "SUBMITTED" if outcome == "submitted" else "EXECUTION_BLOCKED",
"submitted_orders": [{"symbol": "IBIT"}] if outcome == "submitted" else [],
"execution_blocked": outcome == "blocked",
}

def cycle(**kwargs):
cycle_calls.append(kwargs)
if outcome == "exception":
raise failure
return result

monkeypatch.setattr(main, "run_strategy_cycle", cycle)
monkeypatch.setattr(main, "_persist_runtime_report", lambda report: persisted.append(report))
if outcome == "exception":
with pytest.raises(RuntimeError) as caught:
main._run_strategy_cycle_with_report(dry_run_override=dry_run)
assert caught.value is failure
else:
assert main._run_strategy_cycle_with_report(dry_run_override=dry_run) is result

assert len(cycle_calls) == 1
if dry_run:
settings = cycle_calls[0]["runtime_settings"]
assert settings.live_trading_enabled is False
assert settings.runtime_target.execution_environment.value == "dry_run"
assert len(persisted) == 1
report = persisted[0]
assert report["runtime_release_receipt"]["attestation_state"] == "legacy_unattested"
assert "execution_receipt" not in report
assert report["dry_run"] is dry_run
assert report["status"] == ("ok" if outcome == "submitted" else "error")
if outcome == "exception":
assert report["errors"][0]["error_type"] == "RuntimeError"


def test_cloud_run_route_contracts_are_registered():
assert route_methods() == {
"/": ["GET"],
Expand Down