127 lines
4.3 KiB
Python
127 lines
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
# Lightweight, permissive DSL primitives to support MVP tests.
|
|
|
|
class Asset:
|
|
def __init__(self, **kwargs):
|
|
self.__dict__.update(kwargs)
|
|
|
|
class MarketSignal:
|
|
def __init__(self, asset=None, price=0.0, timestamp=0.0, delta=None, meta=None):
|
|
self.asset = asset
|
|
self.price = price
|
|
self.timestamp = timestamp
|
|
self.delta = delta
|
|
self.meta = meta or {}
|
|
|
|
class StrategyDelta:
|
|
def __init__(self, **kwargs):
|
|
self.__dict__.update(kwargs)
|
|
|
|
class PlanDelta:
|
|
def __init__(self, **kwargs):
|
|
self.__dict__.update(kwargs)
|
|
# Backwards-compat: expose both 'deltas' and 'delta'
|
|
if hasattr(self, "deltas") and not hasattr(self, "delta"):
|
|
self.delta = self.deltas
|
|
if hasattr(self, "delta") and not hasattr(self, "deltas"):
|
|
self.deltas = self.delta
|
|
|
|
# Lightweight compatibility helpers used by MVP tests or runtime
|
|
@property
|
|
def total_cost(self):
|
|
# Basic summation of hedge-like entries, if present.
|
|
entries = []
|
|
if getattr(self, "deltas", None):
|
|
entries = list(self.deltas)
|
|
elif getattr(self, "delta", None):
|
|
entries = list(self.delta)
|
|
total = 0.0
|
|
for e in entries:
|
|
if isinstance(e, dict):
|
|
total += float(e.get("size", 0.0)) * float(e.get("price", 0.0))
|
|
else:
|
|
s = getattr(e, "size", 0.0)
|
|
p = getattr(e, "price", 0.0)
|
|
total += float(s) * float(p)
|
|
return total
|
|
|
|
@property
|
|
def signature(self): # alias for tests / tooling that may expect this attribute
|
|
return getattr(self, "signature", None)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# EnergiBridge-inspired canonical IR seeds (phase-0 scaffolding)
|
|
# ---------------------------------------------------------------------------
|
|
class LocalArbProblem:
|
|
"""Canonical local arbitration problem descriptor for a venue.
|
|
|
|
This is a lightweight, vendor-agnostic representation used to seed
|
|
adapters and the coordination layer with per-venue objectives.
|
|
"""
|
|
|
|
def __init__(self, id: str | None = None, venue: str | None = None,
|
|
assets: List[Asset] | None = None, objectives: dict | None = None,
|
|
constraints: List | None = None, solver_hint=None):
|
|
self.id = id
|
|
self.venue = venue
|
|
self.assets = assets or [] # list[Asset]
|
|
self.objectives = objectives or {}
|
|
self.constraints = constraints or []
|
|
self.solver_hint = solver_hint
|
|
|
|
|
|
class SharedSignals:
|
|
"""Cross-venue aggregated signals seed for cooperative planning."""
|
|
|
|
def __init__(self, version: str = "v0", signals: List[MarketSignal] | None = None,
|
|
privacy_tag: str | None = None):
|
|
self.version = version
|
|
self.signals = signals or [] # list[MarketSignal]
|
|
self.privacy_tag = privacy_tag
|
|
|
|
|
|
class DualVariables:
|
|
"""Lagrange multipliers state for ADMM-like coordination."""
|
|
|
|
def __init__(self, multipliers: dict | None = None):
|
|
self.multipliers = multipliers or {}
|
|
|
|
|
|
class PrivacyBudget:
|
|
"""Budgeting for privacy and data leakage controls."""
|
|
|
|
def __init__(self, budget: float = 0.0, expiry: float | None = None, leakage_bound: float = 0.0):
|
|
self.budget = budget
|
|
self.expiry = expiry
|
|
self.leakage_bound = leakage_bound
|
|
|
|
|
|
class AuditLog:
|
|
"""Audit/log block attached to messages for provenance."""
|
|
|
|
def __init__(self, entry: str, signer: str | None = None, timestamp: float = 0.0,
|
|
contract_id: str | None = None, version: str | None = None):
|
|
self.entry = entry
|
|
self.signer = signer
|
|
self.timestamp = timestamp
|
|
self.contract_id = contract_id
|
|
self.version = version
|
|
|
|
|
|
class PolicyBlock:
|
|
"""Policy and safety blocks for governance and controls."""
|
|
|
|
def __init__(self, safety: dict | None = None, exposure_controls: dict | None = None):
|
|
self.safety = safety or {}
|
|
self.exposure_controls = exposure_controls or {}
|
|
|
|
|
|
class TimeMonoid:
|
|
"""Deterministic time abstraction to support islanding/replay semantics."""
|
|
|
|
def __init__(self, island_id: str | None = None, timestamp: float = 0.0):
|
|
self.island_id = island_id
|
|
self.timestamp = timestamp
|