diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bd5590b --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +node_modules/ +.npmrc +.env +.env.* +__tests__/ +coverage/ +.nyc_output/ +dist/ +build/ +.cache/ +*.log +.DS_Store +tmp/ +.tmp/ +__pycache__/ +*.pyc +.venv/ +venv/ +*.egg-info/ +.pytest_cache/ +READY_TO_PUBLISH diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..ea1ceb6 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,37 @@ +# BeVault: Architecture and Contribution Guide + +Overview +- BeVault is a modular backbone enforcing and proving Best Execution across multiple equity venues. +- The MVP focuses on a Graph-of-Contracts (GoC) registry, two starter adapters, and deterministic delta-sync with signed deltas. + +Tech Stack (Production-Ready) +- Language: Python 3.8+ +- Core: lightweight dataclasses for LocalArbProblem, SharedSignals, HedgeDelta, AuditLog, PrivacyBudget +- Registry: GoCRegistry and GraphOfContracts with versioned adapters +- Adapters: PriceFeedAdapter, BrokerAdapter (starter) +- Crypto: HMAC-SHA256 based delta signing (pluggable key material) +- Data Contracts: toy DSL seeds as Python dataclasses +- Tests: pytest-based unit tests + +Project Structure +- idea172_bevault_verifiable_best/ + - __init__.py + - core.py + - signing.py + - registry.py + - adapters/ + - __init__.py + - price_feed.py + - broker.py +- tests/ + - test_basic.py +- README.md +- AGENTS.md (this file) +- test.sh +- pyproject.toml +- READY_TO_PUBLISH (empty when ready) + +How to contribute +- Start with the MVP: wire two adapters and ensure delta-signing and delta-sync are deterministic. +- Expand the GoC registry with new contracts/adapters following the toy DSL seeds. +- Ensure tests cover core contracts, registry operations, and adapter conformance checks. diff --git a/README.md b/README.md index ba72b99..ef3c7df 100644 --- a/README.md +++ b/README.md @@ -1,3 +1 @@ -# idea172-bevault-verifiable-best - -Source logic for Idea #172 \ No newline at end of file +# BeVault: Verifiable Best-Execution Backbone (MVP) diff --git a/idea172_bevault_verifiable_best/__init__.py b/idea172_bevault_verifiable_best/__init__.py new file mode 100644 index 0000000..1cce80b --- /dev/null +++ b/idea172_bevault_verifiable_best/__init__.py @@ -0,0 +1,16 @@ +"""BeVault Verifiable Best-Execution Core (package init).""" + +from .core import LocalArbProblem, SharedSignals, HedgeDelta, AuditLog, PrivacyBudget +from .registry import GoCRegistry, GraphOfContracts +from .signing import sign_delta + +__all__ = [ + "LocalArbProblem", + "SharedSignals", + "HedgeDelta", + "AuditLog", + "PrivacyBudget", + "GoCRegistry", + "GraphOfContracts", + "sign_delta", +] diff --git a/idea172_bevault_verifiable_best/adapters/__init__.py b/idea172_bevault_verifiable_best/adapters/__init__.py new file mode 100644 index 0000000..42c5b2d --- /dev/null +++ b/idea172_bevault_verifiable_best/adapters/__init__.py @@ -0,0 +1,5 @@ +"""Adapter base package for BeVault MVP (price feed, broker).""" +from .price_feed import PriceFeedAdapter +from .broker import BrokerAdapter + +__all__ = ["PriceFeedAdapter", "BrokerAdapter"] diff --git a/idea172_bevault_verifiable_best/adapters/broker.py b/idea172_bevault_verifiable_best/adapters/broker.py new file mode 100644 index 0000000..1166a46 --- /dev/null +++ b/idea172_bevault_verifiable_best/adapters/broker.py @@ -0,0 +1,19 @@ +"""Starter BrokerAdapter for BeVault MVP.""" +from __future__ import annotations +from dataclasses import dataclass + +from ..core import HedgeDelta + + +@dataclass +class BrokerAdapter: + name: str = "broker-v1" + version: str = "0.1" + + def send_delta(self, delta: HedgeDelta) -> bool: + # Placeholder: in real life this would push to venue/execution system + # Here we simply return True to indicate success + return True + + +__all__ = ["BrokerAdapter"] diff --git a/idea172_bevault_verifiable_best/adapters/price_feed.py b/idea172_bevault_verifiable_best/adapters/price_feed.py new file mode 100644 index 0000000..c943158 --- /dev/null +++ b/idea172_bevault_verifiable_best/adapters/price_feed.py @@ -0,0 +1,19 @@ +"""Starter PriceFeedAdapter for BeVault MVP.""" +from __future__ import annotations +from dataclasses import dataclass + +from ..core import HedgeDelta + + +@dataclass +class PriceFeedAdapter: + name: str = "price-feed-v1" + version: str = "0.1" + + def generate_signal(self, asset: str, price: float, latency_ms: float) -> HedgeDelta: + # Produce a minimal HedgeDelta as a placeholder signal payload + # In a real system this would produce SharedSignals -> local arb -> delta + return HedgeDelta(asset=asset, hedge_size=price, timestamp=latency_ms, policy_tag="price-feed") + + +__all__ = ["PriceFeedAdapter"] diff --git a/idea172_bevault_verifiable_best/core.py b/idea172_bevault_verifiable_best/core.py new file mode 100644 index 0000000..f45982d --- /dev/null +++ b/idea172_bevault_verifiable_best/core.py @@ -0,0 +1,53 @@ +"""Core data contracts for BeVault MVP (toy DSL seeds).""" +from __future__ import annotations +from dataclasses import dataclass, field +from typing import List, Optional +import time + + +@dataclass +class LocalArbProblem: + asset: str + objective: str # e.g., 'min_cost', 'maximize_profit' + risk_budget: float + constraints: dict = field(default_factory=dict) + + +@dataclass +class SharedSignals: + asset: str + price: float + latency_ms: float + timestamp: float = field(default_factory=lambda: time.time()) + metadata: dict = field(default_factory=dict) + + +@dataclass +class HedgeDelta: + asset: str + hedge_size: float + timestamp: float = field(default_factory=lambda: time.time()) + policy_tag: str = "default" + signature: Optional[str] = None + + +@dataclass +class AuditLog: + events: List[str] = field(default_factory=list) + entry_ts: float = field(default_factory=lambda: time.time()) + + +@dataclass +class PrivacyBudget: + asset: str + remaining: float + reset_epoch: float = field(default_factory=lambda: time.time()) + + +__all__ = [ + "LocalArbProblem", + "SharedSignals", + "HedgeDelta", + "AuditLog", + "PrivacyBudget", +] diff --git a/idea172_bevault_verifiable_best/registry.py b/idea172_bevault_verifiable_best/registry.py new file mode 100644 index 0000000..f891b78 --- /dev/null +++ b/idea172_bevault_verifiable_best/registry.py @@ -0,0 +1,47 @@ +"""Graph-of-Contracts (GoC) registry and minimal adapters registry. + +This is a lightweight, production-oriented scaffold for the MVP. +""" +from __future__ import annotations +from dataclasses import dataclass, field +from typing import Dict, Optional + +from .core import HedgeDelta +# Import adapters to ensure their classes are discoverable when registry loads +from .adapters.price_feed import PriceFeedAdapter +from .adapters.broker import BrokerAdapter + + +@dataclass +class GoCRegistry: + """Registry for adapters and data contracts (toy GoC).""" + adapters: Dict[str, object] = field(default_factory=dict) + + def __post_init__(self): + # Initialize to an empty mapping if not provided + if self.adapters is None: + self.adapters = {} + + def register_adapter(self, adapter) -> None: + self.adapters[adapter.name] = adapter + + def get_adapter(self, name: str) -> Optional[object]: + return self.adapters.get(name) + + +class GraphOfContracts: + """Lightweight catalog for contract versions and replay metadata.""" + def __init__(self) -> None: + self.contracts: Dict[str, str] = {} + + def register_contract(self, name: str, version: str) -> None: + self.contracts[name] = version + + def get_contract(self, name: str) -> Optional[str]: + return self.contracts.get(name) + + def list_contracts(self): + return list(self.contracts.items()) + + +__all__ = ["GoCRegistry", "GraphOfContracts"] diff --git a/idea172_bevault_verifiable_best/signing.py b/idea172_bevault_verifiable_best/signing.py new file mode 100644 index 0000000..64209bf --- /dev/null +++ b/idea172_bevault_verifiable_best/signing.py @@ -0,0 +1,18 @@ +"""Delta signing utilities for BeVault MVP.""" +from __future__ import annotations +import hmac +import hashlib +from .core import HedgeDelta + + +def sign_delta(delta: HedgeDelta, key: bytes) -> str: + """Sign a HedgeDelta deterministically using HMAC-SHA256. + + The signature is derived from the delta contents (asset, hedge_size, timestamp, policy_tag). + The resulting hex digest is stable for identical inputs and keys. + """ + payload = f"{delta.asset}:{delta.hedge_size}:{delta.timestamp}:{delta.policy_tag}" + return hmac.new(key, payload.encode("utf-8"), hashlib.sha256).hexdigest() + + +__all__ = ["sign_delta"] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..d73a492 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,16 @@ +[build-system] +requires = ["setuptools>=42", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "idea172_bevault_verifiable_best" +version = "0.1.0" +description = "BeVault: verifiable best-execution backbone prototype with Cross-Venue GoC adapters" +readme = "README.md" +requires-python = ">=3.8" +license = {text = "MIT"} +authors = [ { name = "OpenCode Team" } ] + +[tool.setuptools.packages.find] +where = ["."] +include = ["idea172_bevault_verifiable_best", "idea172_bevault_verifiable_best.*"] diff --git a/test.sh b/test.sh new file mode 100644 index 0000000..3f6fbc5 --- /dev/null +++ b/test.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -euo pipefail + +echo "[BeVault] Running tests and packaging sanity checks..." + +# Ensure pip tooling is up to date +python3 -m pip install --upgrade pip setuptools wheel + +# Install the package in editable mode for testing imports +python3 -m pip install -e . + +# Run tests +pytest -q + +# Build the package to verify packaging metadata and directory structure +python3 -m build + +echo "[BeVault] All tests passed and build succeeded." diff --git a/tests/test_basic.py b/tests/test_basic.py new file mode 100644 index 0000000..c37b2f4 --- /dev/null +++ b/tests/test_basic.py @@ -0,0 +1,23 @@ +"""Basic tests for BeVault MVP components.""" +import pytest + +from idea172_bevault_verifiable_best.core import HedgeDelta +from idea172_bevault_verifiable_best.signing import sign_delta +from idea172_bevault_verifiable_best.registry import GoCRegistry +from idea172_bevault_verifiable_best.adapters.price_feed import PriceFeedAdapter + + +def test_sign_delta_deterministic(): + delta = HedgeDelta(asset="AAPL", hedge_size=1.0, timestamp=1.0, policy_tag="test") + key = b"secret-key" + sig1 = sign_delta(delta, key) + sig2 = sign_delta(delta, key) + assert isinstance(sig1, str) and isinstance(sig2, str) + assert sig1 == sig2 + + +def test_registry_adapters_can_register_and_retrieve(): + reg = GoCRegistry() + adapter = PriceFeedAdapter() + reg.register_adapter(adapter) + assert reg.get_adapter(adapter.name) is adapter