idea172-bevault-verifiable-.../idea172_bevault_verifiable_.../core.py

134 lines
3.6 KiB
Python

"""Core data contracts for BeVault."""
from __future__ import annotations
import json
import time
from dataclasses import asdict, dataclass, field
from typing import Any, Dict, List, Optional
@dataclass
class LocalArbProblem:
asset: str
objective: str # e.g., 'min_cost', 'maximize_profit'
risk_budget: float
constraints: Dict[str, Any] = field(default_factory=dict)
def validate(self) -> None:
if not self.asset:
raise ValueError("asset is required")
if self.risk_budget < 0:
raise ValueError("risk_budget must be non-negative")
def to_dict(self) -> Dict[str, Any]:
return asdict(self)
@dataclass
class SharedSignals:
asset: str
price: float
latency_ms: float
timestamp: float = field(default_factory=lambda: time.time())
metadata: Dict[str, Any] = field(default_factory=dict)
def to_dict(self) -> Dict[str, Any]:
return asdict(self)
def is_fresh(self, max_age_seconds: float, now: Optional[float] = None) -> bool:
now = time.time() if now is None else now
return (now - self.timestamp) <= max_age_seconds
@dataclass
class HedgeDelta:
asset: str
hedge_size: float
timestamp: float = field(default_factory=lambda: time.time())
policy_tag: str = "default"
signature: Optional[str] = None
version_vector: Dict[str, int] = field(default_factory=dict)
audit_ref: Optional[str] = None
def to_signable_dict(self) -> Dict[str, Any]:
return {
"asset": self.asset,
"hedge_size": self.hedge_size,
"timestamp": self.timestamp,
"policy_tag": self.policy_tag,
"version_vector": self.version_vector,
"audit_ref": self.audit_ref,
}
def to_json(self) -> str:
return json.dumps(self.to_signable_dict(), sort_keys=True, separators=(",", ":"))
@dataclass
class AuditLog:
events: List[Dict[str, Any]] = field(default_factory=list)
entry_ts: float = field(default_factory=lambda: time.time())
def record(self, event_type: str, payload: Optional[Dict[str, Any]] = None) -> None:
self.events.append(
{
"event_type": event_type,
"payload": payload or {},
"timestamp": time.time(),
}
)
@dataclass
class PrivacyBudget:
asset: str
remaining: float
reset_epoch: float = field(default_factory=lambda: time.time())
def consume(self, amount: float) -> bool:
if amount < 0:
raise ValueError("amount must be non-negative")
if amount > self.remaining:
return False
self.remaining -= amount
return True
__all__ = [
"LocalArbProblem",
"SharedSignals",
"HedgeDelta",
"AuditLog",
"PrivacyBudget",
# Toy DSL seed helper (MVP utility)
"generate_toy_seed",
]
def generate_toy_seed(asset: str = "AAPL", price: float = 100.0):
"""Generate a minimal toy DSL seed pair for MVP testing.
Returns a tuple of (LocalArbProblem, SharedSignals) suitable for
driving a toy cross-venue hedge scenario and deterministic delta-sync
tests without requiring real market data.
This helper is intentionally lightweight and is meant for local testing
and documentation purposes within the MVP boundaries.
"""
local = LocalArbProblem(
asset=asset,
objective="min_cost",
risk_budget=float(price) * 0.1,
constraints={},
)
signals = SharedSignals(
asset=asset,
price=price,
latency_ms=0.5,
timestamp=time.time(),
metadata={"toy_seed": True},
)
return local, signals