From 24c10b482538d14070fb535a2e4f2e37b4f135bf Mon Sep 17 00:00:00 2001 From: agent-58ba63c88b4c9625 Date: Sun, 19 Apr 2026 22:32:32 +0200 Subject: [PATCH] build(agent): new-agents-4#58ba63 iteration --- idea159_arbsphere_federated_cross/__init__.py | 4 +- .../adapters/mock_broker.py | 15 +++++ .../adapters/mock_price_feed.py | 27 +++++++++ idea159_arbsphere_federated_cross/core.py | 28 +++++++++ .../energi_bridge.py | 10 ++++ .../goc_registry.py | 60 +++++++++++++++++++ idea159_arbsphere_federated_cross/solver.py | 14 ++++- 7 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 idea159_arbsphere_federated_cross/adapters/mock_broker.py create mode 100644 idea159_arbsphere_federated_cross/adapters/mock_price_feed.py create mode 100644 idea159_arbsphere_federated_cross/goc_registry.py diff --git a/idea159_arbsphere_federated_cross/__init__.py b/idea159_arbsphere_federated_cross/__init__.py index 6441210..bc86bf7 100644 --- a/idea159_arbsphere_federated_cross/__init__.py +++ b/idea159_arbsphere_federated_cross/__init__.py @@ -5,4 +5,6 @@ minimal bridging utilities to enable interoperability with a canonical IR via EnergiBridge. """ -__all__ = ["core", "solver", "energi_bridge"] +from .goc_registry import GraphOfContracts, GoCAdapter, GoCSchema # re-export for convenience + +__all__ = ["core", "solver", "energi_bridge", "GraphOfContracts", "GoCAdapter", "GoCSchema"] diff --git a/idea159_arbsphere_federated_cross/adapters/mock_broker.py b/idea159_arbsphere_federated_cross/adapters/mock_broker.py new file mode 100644 index 0000000..75a8792 --- /dev/null +++ b/idea159_arbsphere_federated_cross/adapters/mock_broker.py @@ -0,0 +1,15 @@ +from __future__ import annotations + +from datetime import datetime + +from idea159_arbsphere_federated_cross.solver import PlanDelta + + +def route_plan_delta(delta: PlanDelta) -> dict: + """Toy broker that 'executes' a PlanDelta by returning an acknowledgment.""" + # In a real system this would route multiple legs; here we just acknowledge. + return { + "status": "acknowledged", + "timestamp": datetime.utcnow().isoformat() + "Z", + "actions": delta.actions, + } diff --git a/idea159_arbsphere_federated_cross/adapters/mock_price_feed.py b/idea159_arbsphere_federated_cross/adapters/mock_price_feed.py new file mode 100644 index 0000000..2595b9a --- /dev/null +++ b/idea159_arbsphere_federated_cross/adapters/mock_price_feed.py @@ -0,0 +1,27 @@ +from __future__ import annotations + +from datetime import datetime + +from idea159_arbsphere_federated_cross.core import LocalArbProblem, SharedSignals + + +def create_local_arb_problem(venue: str = "EX1", asset_pair: str = "AAPL/GOOGL", target_misprice: float = 0.0, max_exposure: float = 1000.0, latency_budget_ms: int = 50) -> LocalArbProblem: + """Create a toy LocalArbProblem for a given venue.""" + return LocalArbProblem( + id=f"lp-{venue}-{datetime.utcnow().isoformat()}", + venue=venue, + asset_pair=asset_pair, + target_misprice=target_misprice, + max_exposure=max_exposure, + latency_budget_ms=latency_budget_ms, + ) + + +def create_shared_signals(version: int = 1, price_delta: float = 0.0, cross_venue_corr: float = 0.0, liquidity: float = 1.0) -> SharedSignals: + """Create toy SharedSignals for the bridge.""" + return SharedSignals( + version=version, + price_delta=price_delta, + cross_venue_corr=cross_venue_corr, + liquidity=liquidity, + ) diff --git a/idea159_arbsphere_federated_cross/core.py b/idea159_arbsphere_federated_cross/core.py index f08392e..738244c 100644 --- a/idea159_arbsphere_federated_cross/core.py +++ b/idea159_arbsphere_federated_cross/core.py @@ -1,6 +1,7 @@ from __future__ import annotations from dataclasses import dataclass +from datetime import datetime @dataclass @@ -21,4 +22,31 @@ class SharedSignals: liquidity: float +@dataclass +class DualVariables: + """Federated optimization multipliers (shadow prices).""" + multipliers: dict + version: int = 1 + + +@dataclass +class AuditLog: + """Governance or arbitration audit log entry.""" + entry: str + signer: str + timestamp: datetime + contract_id: str + version: int = 1 + + +@dataclass +class PrivacyBudget: + """Privacy budget token for a data-sharing signal.""" + limit: float + remaining: float + expiration: datetime + + +__all__ = ["LocalArbProblem", "SharedSignals", "DualVariables", "AuditLog", "PrivacyBudget"] + __all__ = ["LocalArbProblem", "SharedSignals"] diff --git a/idea159_arbsphere_federated_cross/energi_bridge.py b/idea159_arbsphere_federated_cross/energi_bridge.py index a718db1..a6badf6 100644 --- a/idea159_arbsphere_federated_cross/energi_bridge.py +++ b/idea159_arbsphere_federated_cross/energi_bridge.py @@ -46,6 +46,16 @@ class EnergiBridge: "timestamp": delta.timestamp.isoformat(), } + # Optional governance/provenance extensions + def _to_plain(obj): + return asdict(obj) if hasattr(obj, "__dataclass_fields__") else obj + if getattr(delta, "dual_variables", None) is not None: + payload["DualVariables"] = _to_plain(delta.dual_variables) + if getattr(delta, "audit_log", None) is not None: + payload["AuditLog"] = _to_plain(delta.audit_log) + if getattr(delta, "privacy_budget", None) is not None: + payload["PrivacyBudget"] = _to_plain(delta.privacy_budget) + return payload @staticmethod diff --git a/idea159_arbsphere_federated_cross/goc_registry.py b/idea159_arbsphere_federated_cross/goc_registry.py new file mode 100644 index 0000000..4e7e39e --- /dev/null +++ b/idea159_arbsphere_federated_cross/goc_registry.py @@ -0,0 +1,60 @@ +from __future__ import annotations + +from dataclasses import dataclass, asdict +from datetime import datetime +from typing import Dict, List, Optional, Any + + +@dataclass +class GoCAdapter: + name: str + description: str + version: str + registered_at: datetime + + +@dataclass +class GoCSchema: + adapter_name: str + message_type: str + version: int + metadata: Dict[str, Any] + registered_at: datetime + + +class GraphOfContracts: + """Lightweight in-memory registry describing adapters and data schemas.""" + + def __init__(self) -> None: + self.adapters: Dict[str, GoCAdapter] = {} + self.schemas: List[GoCSchema] = [] + + # Adapter lifecycle + def register_adapter(self, name: str, description: str, version: str) -> GoCAdapter: + adapter = GoCAdapter(name=name, description=description, version=version, registered_at=datetime.utcnow()) + self.adapters[name] = adapter + return adapter + + def get_adapter(self, name: str) -> Optional[GoCAdapter]: + return self.adapters.get(name) + + # Schema registry + def register_schema(self, adapter_name: str, message_type: str, version: int, metadata: Optional[Dict[str, Any]] = None) -> GoCSchema: + schema = GoCSchema( + adapter_name=adapter_name, + message_type=message_type, + version=version, + metadata=metadata or {}, + registered_at=datetime.utcnow(), + ) + self.schemas.append(schema) + return schema + + def to_dict(self) -> Dict[str, Any]: + return { + "adapters": {k: asdict(v) for k, v in self.adapters.items()}, + "schemas": [asdict(s) for s in self.schemas], + } + + +__all__ = ["GraphOfContracts", "GoCAdapter", "GoCSchema"] diff --git a/idea159_arbsphere_federated_cross/solver.py b/idea159_arbsphere_federated_cross/solver.py index 927b5c0..1d10443 100644 --- a/idea159_arbsphere_federated_cross/solver.py +++ b/idea159_arbsphere_federated_cross/solver.py @@ -5,9 +5,20 @@ from .core import LocalArbProblem, SharedSignals class PlanDelta: - def __init__(self, actions, timestamp: datetime | None = None): + def __init__( + self, + actions, + timestamp: datetime | None = None, + dual_variables=None, + audit_log=None, + privacy_budget=None, + ): self.actions = actions self.timestamp = timestamp or datetime.utcnow() + # Optional extensions for advanced governance/provenance. + self.dual_variables = dual_variables + self.audit_log = audit_log + self.privacy_budget = privacy_budget def admm_step(local: LocalArbProblem, signals: SharedSignals) -> PlanDelta: @@ -29,6 +40,7 @@ def admm_step(local: LocalArbProblem, signals: SharedSignals) -> PlanDelta: "time": datetime.utcnow().isoformat() + "Z", } + # In this minimal MVP, we don't yet populate dual/audit/privacy here. return PlanDelta(actions=[action])