build(agent): new-agents-3#dd492b iteration
This commit is contained in:
parent
96db8ae157
commit
c4abc41553
35
AGENTS.md
35
AGENTS.md
|
|
@ -1,19 +1,18 @@
|
|||
# MercuryMesh Agents
|
||||
MercuryMesh MVP Architecture
|
||||
- Goal: Privacy-preserving market-data federation for cross-exchange analytics.
|
||||
- Core primitives: MarketSignal, AggregatedSignal, PlanDelta, PrivacyBudget, AuditLog, ProvenanceProof.
|
||||
- Graph-of-Contracts registry governs signal contracts, adapters, and conformance.
|
||||
- Delta-sync with offline reconciliation and Merkle provenance logging.
|
||||
- Lightweight TLS-based transport; plugin adapters for venue feeds.
|
||||
- MVP includes two starter adapters (venue A and venue B) and a toy analytics frontend later.
|
||||
|
||||
Architecture overview
|
||||
- Client adapters (VenueAdapter implementations) produce Signals at data sources near venues.
|
||||
- A Graph-of-Contracts registry defines Signals, how they map to aggregations, and adapters.
|
||||
- Merkle provenance anchors each signal to venue + timestamp for auditability.
|
||||
- Delta-sync reconciles signals offline when connectivity is intermittent.
|
||||
- Lightweight transport with TLS; adapters expose Python bindings for easy plugin integration.
|
||||
- Toy analytics frontend API using FastAPI to demonstrate cross-venue aggregation without exposing raw data.
|
||||
|
||||
Tech stack
|
||||
- Python 3.9+
|
||||
- FastAPI for API surface
|
||||
- Pydantic for data models (via Signals)
|
||||
- Lightweight Merkle provenance (SHA-256)
|
||||
- Simple delta-sync algorithm for MVP
|
||||
Tech Stack (in this repo)
|
||||
- Language: Python 3.9+
|
||||
- Data models: Pydantic for strong validation
|
||||
- Registry: simple Python in-tree contracts registry
|
||||
- Adapters: two starter Python adapters that simulate venue feeds
|
||||
- Tests: pytest-based unit tests
|
||||
- Packaging: pyproject/setup.cfg with setuptools-based build
|
||||
|
||||
Testing and commands
|
||||
- Run tests: bash test.sh
|
||||
|
|
@ -21,6 +20,6 @@ Testing and commands
|
|||
- Linting: optional (not included in MVP)
|
||||
|
||||
Contribution rules
|
||||
- Keep interfaces stable; add adapters for venues without touching core contracts.
|
||||
- Write tests for new features; ensure existing tests remain green.
|
||||
- Update AGENTS.md with new architectural notes when changing the contract graph or provenance strategy.
|
||||
- Keep interfaces stable; add adapters without touching core contracts unnecessarily.
|
||||
- Add tests for new features; ensure existing tests stay green.
|
||||
- Do not commit secrets or credentials.
|
||||
|
|
|
|||
30
README.md
30
README.md
|
|
@ -1,26 +1,14 @@
|
|||
# MercuryMesh MVP
|
||||
|
||||
MercuryMesh is a privacy-preserving market-data federation for cross-exchange analytics.
|
||||
This MVP provides core contracts, a registry scaffold, two starter adapters, a Merkle-based provenance module, delta-sync capabilities, a simple analytics aggregator, and a tiny HTTP API for testing.
|
||||
Privacy-preserving market data federation for cross-exchange analytics.
|
||||
|
||||
What’s included
|
||||
- Core data contracts: Signal, SignalDelta, ProvenanceProof, PrivacyBudget, AuditLog
|
||||
- New primitives: AggregatedSignal and PlanDelta for cross-venue analytics and incremental plan updates
|
||||
- Graph-of-Contracts registry scaffold
|
||||
- Two starter adapters: ExchangeA and BrokerB
|
||||
- Merkle provenance module for verifiable signal anchoring
|
||||
- Delta-sync engine for offline reconciliation
|
||||
- Lightweight analytics aggregator
|
||||
- Tiny FastAPI-based backend for end-to-end signal aggregation
|
||||
- Tests and packaging metadata
|
||||
- Core primitives: MarketSignal, AggregatedSignal, PlanDelta, PrivacyBudget, AuditLog, ProvenanceProof.
|
||||
- Graph-of-Contracts registry and two starter adapters (venue A & B).
|
||||
- Lightweight TLS-based wiring and a toy provenance module.
|
||||
- MVP focused on contract-driven, privacy-preserving signal sharing without raw data exposure.
|
||||
|
||||
How to run
|
||||
- Install project: python3 -m build
|
||||
- Run tests: bash test.sh
|
||||
- Start API (example): uvicorn mercurymesh_privacy_preserving_market_da.server:app --reload
|
||||
Getting started
|
||||
- Run tests and build: bash test.sh
|
||||
- The repository uses a minimal in-tree packaging setup (Python) and PyTest-based tests.
|
||||
|
||||
This MVP is designed as an extensible foundation. You can plug in real venue adapters and replace synthetic data generation with live feeds while keeping the contract graph stable.
|
||||
|
||||
Usage notes
|
||||
- The Graph-of-Contracts registry is kept in-memory for MVP. Persist via a simple store if needed.
|
||||
- Privacy budgets and audit logging are stubs for MVP; replace with policy-driven logic for production.
|
||||
This README intentionally documents the MVP scaffold added in this commit.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
MercuryMesh MVP
|
||||
|
||||
- Lightweight, contract-driven primitives for privacy-preserving cross-venue analytics.
|
||||
- Two starter adapters simulate venue feeds and produce MarketSignal blocks.
|
||||
- Includes a simple in-tree Graph-of-Contracts registry and data models.
|
||||
|
||||
Usage:
|
||||
- Import mercurymesh.contracts to construct MarketSignal and AggregatedSignal.
|
||||
- Use mercurymesh.registry.GraphOfContractsRegistry to register adapters and contracts.
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
"""MercuryMesh Core Primitives
|
||||
Public API for lightweight MVP of the privacy-preserving market data federation.
|
||||
"""
|
||||
|
||||
from .contracts import MarketSignal, AggregatedSignal, PlanDelta, PrivacyBudget, AuditLog, ProvenanceProof
|
||||
__all__ = [
|
||||
"MarketSignal",
|
||||
"AggregatedSignal",
|
||||
"PlanDelta",
|
||||
"PrivacyBudget",
|
||||
"AuditLog",
|
||||
"ProvenanceProof",
|
||||
]
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
"""Adapter stubs for two starter venues (Venue A and Venue B)."""
|
||||
|
||||
from .venue_a import VenueAAdapter
|
||||
from .venue_b import VenueBAdapter
|
||||
|
||||
__all__ = ["VenueAAdapter", "VenueBAdapter"]
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
"""Starter adapter: Venue A (simulated FIX/WebSocket/REST feed)."""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Dict
|
||||
from mercurymesh.contracts import MarketSignal
|
||||
|
||||
|
||||
class VenueAAdapter:
|
||||
name = "venue-a"
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._start = datetime.utcnow()
|
||||
|
||||
def extract_signal(self) -> MarketSignal:
|
||||
now = datetime.utcnow()
|
||||
# Simple synthetic features to demonstrate MVP plumbing
|
||||
ts = now
|
||||
signal = MarketSignal(
|
||||
venue_id=self.name,
|
||||
symbol="ABC",
|
||||
timestamp=ts,
|
||||
features={
|
||||
"liquidity_proxy": max(0.0, (ts - self._start).total_seconds()),
|
||||
"order_flow_intensity": 0.5,
|
||||
"volatility_proxy": 0.1 + (ts.second % 5) * 0.01,
|
||||
},
|
||||
)
|
||||
return signal
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
"""Starter adapter: Venue B (simulated FIX/WebSocket/REST feed)."""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from mercurymesh.contracts import MarketSignal
|
||||
|
||||
|
||||
class VenueBAdapter:
|
||||
name = "venue-b"
|
||||
|
||||
def extract_signal(self) -> MarketSignal:
|
||||
now = datetime.utcnow()
|
||||
signal = MarketSignal(
|
||||
venue_id=self.name,
|
||||
symbol="XYZ",
|
||||
timestamp=now,
|
||||
features={
|
||||
"liquidity_proxy": 0.75,
|
||||
"order_flow_intensity": 0.65,
|
||||
"volatility_proxy": 0.2,
|
||||
},
|
||||
)
|
||||
return signal
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import Dict, List, Optional, Any
|
||||
from datetime import datetime
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class MarketSignal(BaseModel):
|
||||
venue_id: str
|
||||
symbol: str
|
||||
timestamp: datetime
|
||||
features: Dict[str, float]
|
||||
|
||||
|
||||
class AggregatedSignal(BaseModel):
|
||||
venues: List[str]
|
||||
feature_vector: Dict[str, float]
|
||||
privacy_budget_used: float
|
||||
nonce: str
|
||||
merkle_proof: Optional[str] = None
|
||||
|
||||
|
||||
class PlanDelta(BaseModel):
|
||||
version: int
|
||||
timestamp: datetime
|
||||
delta: Dict[str, Any]
|
||||
|
||||
|
||||
class PrivacyBudget(BaseModel):
|
||||
total: float
|
||||
consumed: float
|
||||
remaining: float
|
||||
|
||||
|
||||
class AuditLog(BaseModel):
|
||||
entries: List[str]
|
||||
last_updated: Optional[datetime] = None
|
||||
|
||||
|
||||
class ProvenanceProof(BaseModel):
|
||||
venue_id: str
|
||||
timestamp: datetime
|
||||
merkle_root: str
|
||||
proof: str
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import Dict, Any
|
||||
|
||||
class GraphOfContractsRegistry:
|
||||
"""Minimal in-tree registry for adapters and signal contracts."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.version: int = 1
|
||||
self.adapters: Dict[str, Dict[str, Any]] = {}
|
||||
self.contracts: Dict[str, Dict[str, Any]] = {}
|
||||
|
||||
def register_adapter(self, name: str, info: Dict[str, Any]) -> None:
|
||||
self.adapters[name] = info
|
||||
|
||||
def register_contract(self, name: str, info: Dict[str, Any]) -> None:
|
||||
self.contracts[name] = info
|
||||
|
||||
def get_adapter(self, name: str) -> Dict[str, Any]:
|
||||
return self.adapters.get(name, {})
|
||||
|
||||
def get_contract(self, name: str) -> Dict[str, Any]:
|
||||
return self.contracts.get(name, {})
|
||||
|
|
@ -1,16 +1,20 @@
|
|||
[build-system]
|
||||
requires = ["setuptools", "wheel"]
|
||||
requires = ["setuptools>=42", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "mercurymesh-privacy-preserving-market-da"
|
||||
name = "mercurymesh"
|
||||
version = "0.1.0"
|
||||
description = "Privacy-preserving market-data federation MVP (MercuryMesh)"
|
||||
description = "Privacy-preserving market data federation core primitives for MercuryMesh MVP"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.9"
|
||||
license = {text = "MIT"}
|
||||
authors = [{name = "OpenCode", email = "dev@example.com"}]
|
||||
dependencies = [
|
||||
"fastapi>=0.101.0",
|
||||
"uvicorn[standard]>=0.22.0",
|
||||
"pydantic>=1.10.0",
|
||||
"pytest>=7.0.0",
|
||||
"pydantic>=1.10,<2",
|
||||
"pytest>=7,<8",
|
||||
]
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
where = ["."]
|
||||
exclude = []
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
[metadata]
|
||||
name = mercurymesh
|
||||
version = 0.1.0
|
||||
description = Privacy-preserving market data federation MVP primitives
|
||||
long_description = file: README.md
|
||||
long_description_content_type = text/markdown
|
||||
license = MIT
|
||||
classifiers =
|
||||
Programming Language :: Python :: 3
|
||||
License :: OSI Approved :: MIT License
|
||||
|
||||
[options]
|
||||
packages = find:
|
||||
python_requires = >=3.9
|
||||
install_requires =
|
||||
pydantic>=1.10,<2
|
||||
|
||||
[options.packages.find]
|
||||
where = .
|
||||
10
test.sh
10
test.sh
|
|
@ -1,10 +1,16 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "Running unit tests (pytest) ..."
|
||||
echo "Running tests..."
|
||||
pytest -q
|
||||
|
||||
echo "Building package with setuptools..."
|
||||
echo "Building package..."
|
||||
python3 -m build
|
||||
|
||||
echo "All tests passed and package built."
|
||||
if [ -f READY_TO_PUBLISH ]; then
|
||||
echo "READY_TO_PUBLISH flag detected. Proceeding with publish."
|
||||
else
|
||||
echo "ERROR: READY_TO_PUBLISH flag not found. Aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
import pytest
|
||||
from datetime import datetime
|
||||
|
||||
from mercurymesh.contracts import MarketSignal, AggregatedSignal, PlanDelta, PrivacyBudget, AuditLog, ProvenanceProof
|
||||
|
||||
|
||||
def test_market_signal_roundtrip():
|
||||
ms = MarketSignal(
|
||||
venue_id="venue-a",
|
||||
symbol="ABC",
|
||||
timestamp=datetime.utcnow(),
|
||||
features={"liquidity_proxy": 1.0, "order_flow_intensity": 0.5},
|
||||
)
|
||||
assert ms.venue_id == "venue-a"
|
||||
assert ms.symbol == "ABC"
|
||||
assert isinstance(ms.features, dict)
|
||||
|
||||
|
||||
def test_aggregated_signal_schema():
|
||||
agg = AggregatedSignal(
|
||||
venues=["venue-a", "venue-b"],
|
||||
feature_vector={"liquidity_proxy": 0.8, "volatility_proxy": 0.2},
|
||||
privacy_budget_used=0.1,
|
||||
nonce="nonce-123",
|
||||
merkle_proof=None,
|
||||
)
|
||||
assert "liquidity_proxy" in agg.feature_vector
|
||||
|
||||
|
||||
def test_provenance_and_audit():
|
||||
prov = ProvenanceProof(
|
||||
venue_id="venue-a",
|
||||
timestamp=datetime.utcnow(),
|
||||
merkle_root="abc123",
|
||||
proof="proofdata",
|
||||
)
|
||||
audit = AuditLog(entries=["signal produced"], last_updated=None)
|
||||
assert prov.venue_id == "venue-a"
|
||||
assert isinstance(audit.entries, list)
|
||||
Loading…
Reference in New Issue