diff --git a/arbsphere/__init__.py b/arbsphere/__init__.py index 09f19be..b06bb7a 100644 --- a/arbsphere/__init__.py +++ b/arbsphere/__init__.py @@ -6,15 +6,20 @@ federated arbitrage engine; here we only provide deterministic, testable behaviors. """ -from .primitives import LocalArbProblem, SharedSignals # noqa: F401 +from .primitives import LocalArbProblem, SharedSignals, DualVariables, AuditLog, PrivacyBudget # noqa: F401 from .coordinator import admm_lite_step # noqa: F401 from .ir import map_to_ir # noqa: F401 from .go_registry import GoCRegistry # noqa: F401 +from .two_venue_demo import run_demo # noqa: F401 __all__ = [ "LocalArbProblem", "SharedSignals", + "DualVariables", + "AuditLog", + "PrivacyBudget", "admm_lite_step", "map_to_ir", "GoCRegistry", + "run_demo", ] diff --git a/arbsphere/primitives.py b/arbsphere/primitives.py index d8fac92..00ca84f 100644 --- a/arbsphere/primitives.py +++ b/arbsphere/primitives.py @@ -1,5 +1,5 @@ from dataclasses import dataclass -from typing import List, Tuple, Dict +from typing import List, Tuple, Dict, Any @dataclass(frozen=True) @@ -16,3 +16,32 @@ class SharedSignals: cross_venue_corr: float liquidity_availability: Dict[str, float] latency_proxy: float + + +@dataclass +class DualVariables: + """Federated optimization dual variables (shadow prices per asset pair). + + This is a lightweight stand-in for the real project's duals used by the + ADMM-like coordinator to balance cross-venue objectives. + """ + shadow_prices: Dict[str, float] + + +@dataclass +class AuditLogEntry: + ts: float + event: str + details: Dict[str, Any] + signature: str + + +@dataclass +class AuditLog: + entries: List[AuditLogEntry] + + +@dataclass +class PrivacyBudget: + """Simple privacy budget per signal source or metric.""" + budgets: Dict[str, float] diff --git a/arbsphere/two_venue_demo.py b/arbsphere/two_venue_demo.py new file mode 100644 index 0000000..237f04c --- /dev/null +++ b/arbsphere/two_venue_demo.py @@ -0,0 +1,57 @@ +from __future__ import annotations + +"""Toy two-venue ArbSphere demo. + +This module wires two toy adapters (price feed and broker) from two venues +and demonstrates a minimal federated compute step using the existing ADMM-lite +coordinator API. +""" + +import time +from typing import List +from arbsphere.primitives import LocalArbProblem, SharedSignals +from arbsphere.coordinator import admm_lite_step +from arbsphere.adapters.price_feed_adapter import PriceFeedAdapter +from arbsphere.adapters.broker_adapter import BrokerAdapter + + +def run_demo() -> None: + # Define two toy venues with simple, deterministic budgets + lp1 = LocalArbProblem(asset_pair=("AAPL", "MSFT"), target_mispricing=0.5, liquidity_budget=1000.0, latency_budget=5.0) + lp2 = LocalArbProblem(asset_pair=("GOOG", "AMZN"), target_mispricing=0.7, liquidity_budget=800.0, latency_budget=6.0) + + shared = SharedSignals( + deltas=[0.1, -0.05], + cross_venue_corr=0.25, + liquidity_availability={"venue-1": 0.8, "venue-2": 0.75}, + latency_proxy=0.9, + ) + + # Step 1: compute a delta (toy) via admm_lite_step + delta = admm_lite_step([lp1, lp2], shared) + + print("Generated PlanDelta:") + print(delta) + + # Step 2: route using toy broker adapters (two venues) + broker_a = BrokerAdapter(venue_name="venue-1") + broker_b = BrokerAdapter(venue_name="venue-2") + + # Create simple per-venue plan deltas; in a real system this would be split by venue + plan_for_venue_a = {"legs": delta.legs, "total_size": delta.total_size} + plan_for_venue_b = {"legs": delta.legs, "total_size": delta.total_size} + + broker_a.route(plan_for_venue_a) + broker_b.route(plan_for_venue_b) + + print("Venue-1 execution history:", broker_a.history()) + print("Venue-2 execution history:", broker_b.history()) + + +def main() -> None: + print("Starting ArbSphere two-venue demo...") + run_demo() + + +if __name__ == "__main__": + main()