build(agent): new-agents-2#7e3bbc iteration
This commit is contained in:
parent
7668af7fe2
commit
25822f2b4e
|
|
@ -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
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
DeltaX-Forge SWARM Agent Guide
|
||||||
|
|
||||||
|
Overview
|
||||||
|
- DeltaX-Forge is a cross-venue delta-driven execution planner with a canonical DSL and a two-tier solver architecture.
|
||||||
|
- Core stack uses Python for production-grade components: a lightweight DSL, local venue solvers, a central curator, adapters for data feeds and execution, and a governance/logging layer.
|
||||||
|
|
||||||
|
Project Architecture (high level)
|
||||||
|
- deltax_forge_cross/
|
||||||
|
- __init__.py
|
||||||
|
- dsl.py # Canonical StrategyDelta DSL (Assets, Legs, MarketSignal, PlanDelta, AuditLog) (see tests for usage)
|
||||||
|
- deltax_forge_cross/core/
|
||||||
|
- local_venue_solver.py # Local solver implementation
|
||||||
|
- central_curator.py # Central coordination/consensus surrogate
|
||||||
|
- deltax_forge_cross/adapters/
|
||||||
|
- price_feed_adapter.py # Translates MarketSignal to a feed dict
|
||||||
|
- venue_execution_adapter.py # Translates PlanDelta to an execution map
|
||||||
|
- deltax_forge_cross/logging.py # Deterministic replay logging
|
||||||
|
- deltax_forge_cross/ledger.py # Lightweight cryptographic signing (HMAC-based)
|
||||||
|
- tests/ # pytest suite (tests/test_deltax.py)
|
||||||
|
|
||||||
|
Testing and CI
|
||||||
|
- Test command: bash test.sh
|
||||||
|
- test.sh builds, installs, and runs pytest
|
||||||
|
- The tests exercise DSL, local/central solvers, adapters, and governance signing
|
||||||
|
|
||||||
|
How to contribute
|
||||||
|
- Run tests locally with: bash test.sh
|
||||||
|
- Ensure new features have unit tests; keep changes minimal and well-scoped
|
||||||
|
- Maintain backward compatibility unless explicitly required by a breaking change
|
||||||
|
|
||||||
|
Notes
|
||||||
|
- The repository is intentionally self-contained; it provides a minimal MVP for the DeltaX-Forge concept.
|
||||||
21
README.md
21
README.md
|
|
@ -1,3 +1,20 @@
|
||||||
# idea149-deltax-forge-cross
|
# DeltaX-Forge: Cross-Venue Delta-Driven Execution Slicer (MVP)
|
||||||
|
|
||||||
Source logic for Idea #149
|
DeltaX-Forge provides a minimal, production-oriented blueprint for cross-venue hedging using a canonical StrategyDelta DSL, a two-tier solver, and deterministic governance logging.
|
||||||
|
|
||||||
|
- Core DSL: Assets, Legs, MarketSignal, PlanDelta, and AuditLogEntry.
|
||||||
|
- LocalVenueSolver: lightweight per-venue delta computation.
|
||||||
|
- CentralCurator: cross-venue coherence and coordination.
|
||||||
|
- Adapters: price feed and venue execution translations.
|
||||||
|
- Deterministic replay and governance ledger via cryptographic signing.
|
||||||
|
|
||||||
|
How to run tests locally
|
||||||
|
- Ensure Python 3.11+ is available.
|
||||||
|
- Run: bash test.sh
|
||||||
|
- This will build, install, and run the test suite.
|
||||||
|
|
||||||
|
Packaging notes
|
||||||
|
- This repository is designed to be installed from a wheel or sdist. The test script installs the produced wheel before running tests to ensure import paths are resolvable in CI environments.
|
||||||
|
|
||||||
|
Hooked commands
|
||||||
|
- See AGENTS.md for developer-oriented information and testing commands.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
from .dsl import Asset, Leg, MarketSignal, StrategyDelta, PlanDelta, AuditLogEntry
|
||||||
|
from .core.local_venue_solver import LocalVenueSolver
|
||||||
|
from .core.central_curator import CentralCurator
|
||||||
|
from .adapters.price_feed_adapter import translate_market_signals
|
||||||
|
from .adapters.venue_execution_adapter import translate_plan_delta
|
||||||
|
from .logging import RunLog
|
||||||
|
from .ledger import LedgerSigner, sign_and_append
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"Asset",
|
||||||
|
"Leg",
|
||||||
|
"MarketSignal",
|
||||||
|
"StrategyDelta",
|
||||||
|
"PlanDelta",
|
||||||
|
"AuditLogEntry",
|
||||||
|
"LocalVenueSolver",
|
||||||
|
"CentralCurator",
|
||||||
|
"translate_market_signals",
|
||||||
|
"translate_plan_delta",
|
||||||
|
"RunLog",
|
||||||
|
"LedgerSigner",
|
||||||
|
"sign_and_append",
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
"""Starter adapters for DeltaX-Forge interoperability."""
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from deltax_forge_cross.dsl import MarketSignal, StrategyDelta
|
||||||
|
|
||||||
|
|
||||||
|
def translate_market_signals(strategy_delta: StrategyDelta) -> dict:
|
||||||
|
"""Translate MarketSignal objects into a simple feed dictionary."""
|
||||||
|
feeds = {}
|
||||||
|
for s in strategy_delta.signals:
|
||||||
|
feeds[s.symbol] = {
|
||||||
|
"price": s.price,
|
||||||
|
"liquidity": s.liquidity,
|
||||||
|
"latency_proxy": s.latency_proxy,
|
||||||
|
}
|
||||||
|
return feeds
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
from deltax_forge_cross.dsl import PlanDelta
|
||||||
|
|
||||||
|
|
||||||
|
def translate_plan_delta(plan_delta: PlanDelta) -> Dict[str, float]:
|
||||||
|
"""Translate PlanDelta into a simplified execution map per venue.
|
||||||
|
This toy translator simply echoes hedge_updates for downstream execution.
|
||||||
|
"""
|
||||||
|
return dict(plan_delta.hedge_updates)
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Dict, List
|
||||||
|
|
||||||
|
|
||||||
|
class CentralCurator:
|
||||||
|
def __init__(self, venue_ids: List[str]):
|
||||||
|
self.venue_ids = venue_ids
|
||||||
|
|
||||||
|
def coordinate(self, local_deltas: List[Dict[str, float]]) -> Dict[str, float]:
|
||||||
|
if not local_deltas:
|
||||||
|
return {}
|
||||||
|
# Simple average of deltas per asset across venues
|
||||||
|
keys = set().union(*local_deltas) # all asset symbols
|
||||||
|
shared: Dict[str, float] = {}
|
||||||
|
for k in keys:
|
||||||
|
total = sum(d.get(k, 0.0) for d in local_deltas)
|
||||||
|
shared[k] = total / len(local_deltas)
|
||||||
|
return shared
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
|
from deltax_forge_cross.dsl import StrategyDelta
|
||||||
|
|
||||||
|
|
||||||
|
class LocalVenueSolver:
|
||||||
|
def __init__(self, venue_id: str, assets: Optional[List[str]] = None):
|
||||||
|
self.venue_id = venue_id
|
||||||
|
self.assets = assets or []
|
||||||
|
|
||||||
|
def compute_local_delta(self, strategy_delta: StrategyDelta) -> Dict[str, float]:
|
||||||
|
# Very simple heuristic: divide delta_budget evenly across assets present in strategy
|
||||||
|
asset_symbols = [a.symbol for a in strategy_delta.assets] if strategy_delta.assets else []
|
||||||
|
if not asset_symbols:
|
||||||
|
return {}
|
||||||
|
per = strategy_delta.delta_budget / len(asset_symbols)
|
||||||
|
return {sym: per for sym in asset_symbols}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import List, Dict
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Asset:
|
||||||
|
symbol: str
|
||||||
|
kind: str # e.g., 'Equity'
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Leg:
|
||||||
|
asset: Asset
|
||||||
|
target_delta: float
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class MarketSignal:
|
||||||
|
symbol: str
|
||||||
|
price: float
|
||||||
|
liquidity: float
|
||||||
|
latency_proxy: float
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class AuditLogEntry:
|
||||||
|
timestamp: float
|
||||||
|
actor: str
|
||||||
|
action: str
|
||||||
|
note: str
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class PlanDelta:
|
||||||
|
hedge_updates: Dict[str, float] # asset_symbol -> delta
|
||||||
|
authority: str
|
||||||
|
audit_log: List[AuditLogEntry] = field(default_factory=list)
|
||||||
|
|
||||||
|
def to_dict(self) -> Dict:
|
||||||
|
return {
|
||||||
|
"hedge_updates": self.hedge_updates,
|
||||||
|
"authority": self.authority,
|
||||||
|
"audit_log": [
|
||||||
|
{"timestamp": e.timestamp, "actor": e.actor, "action": e.action, "note": e.note}
|
||||||
|
for e in self.audit_log
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class StrategyDelta:
|
||||||
|
delta_budget: float
|
||||||
|
vega_budget: float
|
||||||
|
gamma_budget: float
|
||||||
|
pnl_target: float
|
||||||
|
assets: List[Asset] = field(default_factory=list)
|
||||||
|
legs: List[Leg] = field(default_factory=list)
|
||||||
|
signals: List[MarketSignal] = field(default_factory=list)
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
class LedgerSigner:
|
||||||
|
def __init__(self, key: str):
|
||||||
|
self.key = key
|
||||||
|
|
||||||
|
def sign(self, message: str) -> str:
|
||||||
|
import hmac
|
||||||
|
import hashlib
|
||||||
|
return hmac.new(self.key.encode("utf-8"), message.encode("utf-8"), hashlib.sha256).hexdigest()
|
||||||
|
|
||||||
|
def verify(self, message: str, signature: str) -> bool:
|
||||||
|
return self.sign(message) == signature
|
||||||
|
|
||||||
|
|
||||||
|
def sign_and_append(plan_delta: Any, signer: LedgerSigner, log_path: str = "ledger.log") -> bool:
|
||||||
|
# Convert plan_delta to a portable dict if possible
|
||||||
|
if hasattr(plan_delta, "to_dict"):
|
||||||
|
payload = plan_delta.to_dict()
|
||||||
|
elif isinstance(plan_delta, dict):
|
||||||
|
payload = plan_delta
|
||||||
|
else:
|
||||||
|
payload = {"repr": repr(plan_delta)}
|
||||||
|
|
||||||
|
payload_str = json.dumps(payload, sort_keys=True)
|
||||||
|
signature = signer.sign(payload_str)
|
||||||
|
entry = {"timestamp": time.time(), "payload": payload, "signature": signature}
|
||||||
|
with open(log_path, "a", encoding="utf-8") as f:
|
||||||
|
f.write(json.dumps(entry) + "\n")
|
||||||
|
return True
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
class RunLog:
|
||||||
|
def __init__(self, path: str = "deltax_run.log"):
|
||||||
|
self.path = path
|
||||||
|
|
||||||
|
def log(self, entry: dict) -> None:
|
||||||
|
with open(self.path, "a", encoding="utf-8") as f:
|
||||||
|
payload = {
|
||||||
|
"ts": time.time(),
|
||||||
|
"event": entry,
|
||||||
|
}
|
||||||
|
f.write(json.dumps(payload) + "\n")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def replay(path: str):
|
||||||
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
|
for line in f:
|
||||||
|
if not line.strip():
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
obj = json.loads(line)
|
||||||
|
yield obj
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
continue
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
[build-system]
|
||||||
|
requires = ["setuptools", "wheel"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "idea149-deltax-forge-cross"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "MVP for cross-venue delta-driven execution planning with a canonical DSL and two-tier solver"
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
license = { text = "MIT" }
|
||||||
|
readme = "README.md"
|
||||||
|
dependencies = [
|
||||||
|
"pydantic>=1.10,<2",
|
||||||
|
"pytest; python_version>='3.9'",
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.setuptools.packages.find]
|
||||||
|
where = ["."]
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Build and test DeltaX-Forge project
|
||||||
|
# Steps:
|
||||||
|
# 1) Build sdist+wheel
|
||||||
|
# 2) Install the produced wheel into a clean environment
|
||||||
|
# 3) Run test suite
|
||||||
|
|
||||||
|
echo "[CI] Building distribution..."
|
||||||
|
python3 -m build
|
||||||
|
|
||||||
|
echo "[CI] Installing built wheel..."
|
||||||
|
# Find the produced wheel and install it
|
||||||
|
WHEEL=$(ls dist/*.whl | head -n 1)
|
||||||
|
if [[ -z "$WHEEL" ]]; then
|
||||||
|
echo "No wheel found in dist/; aborting." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
python3 -m pip install --upgrade pip
|
||||||
|
python3 -m pip install "$WHEEL"
|
||||||
|
|
||||||
|
echo "[CI] Running tests..."
|
||||||
|
pytest -q
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
import time
|
||||||
|
from deltax_forge_cross.dsl import Asset, MarketSignal, StrategyDelta, PlanDelta, AuditLogEntry
|
||||||
|
from deltax_forge_cross.core.local_venue_solver import LocalVenueSolver
|
||||||
|
from deltax_forge_cross.core.central_curator import CentralCurator
|
||||||
|
from deltax_forge_cross.adapters.price_feed_adapter import translate_market_signals
|
||||||
|
from deltax_forge_cross.adapters.venue_execution_adapter import translate_plan_delta
|
||||||
|
from deltax_forge_cross.logging import RunLog
|
||||||
|
from deltax_forge_cross.ledger import LedgerSigner, sign_and_append
|
||||||
|
|
||||||
|
|
||||||
|
def test_dsl_creation():
|
||||||
|
a1 = Asset(symbol="AAPL", kind="Equity")
|
||||||
|
a2 = Asset(symbol="MSFT", kind="Equity")
|
||||||
|
ms = MarketSignal(symbol="AAPL", price=150.0, liquidity=0.9, latency_proxy=0.01)
|
||||||
|
strategy = StrategyDelta(
|
||||||
|
delta_budget=10.0,
|
||||||
|
vega_budget=2.0,
|
||||||
|
gamma_budget=1.0,
|
||||||
|
pnl_target=1.0,
|
||||||
|
assets=[a1, a2],
|
||||||
|
signals=[ms],
|
||||||
|
)
|
||||||
|
assert strategy.delta_budget == 10.0
|
||||||
|
assert len(strategy.assets) == 2
|
||||||
|
|
||||||
|
|
||||||
|
def test_local_and_central_coherence():
|
||||||
|
a1 = Asset(symbol="AAPL", kind="Equity")
|
||||||
|
a2 = Asset(symbol="MSFT", kind="Equity")
|
||||||
|
strategy = StrategyDelta(delta_budget=10.0, vega_budget=2.0, gamma_budget=1.0, pnl_target=1.0,
|
||||||
|
assets=[a1, a2])
|
||||||
|
solver1 = LocalVenueSolver("VENUE1", assets=[a1.symbol, a2.symbol])
|
||||||
|
solver2 = LocalVenueSolver("VENUE2", assets=[a1.symbol, a2.symbol])
|
||||||
|
d1 = solver1.compute_local_delta(strategy)
|
||||||
|
d2 = solver2.compute_local_delta(strategy)
|
||||||
|
import pytest
|
||||||
|
curator = CentralCurator(["VENUE1", "VENUE2"])
|
||||||
|
shared = curator.coordinate([d1, d2])
|
||||||
|
assert shared["AAPL"] == pytest.approx(5.0)
|
||||||
|
assert shared["MSFT"] == pytest.approx(5.0)
|
||||||
|
|
||||||
|
|
||||||
|
def test_log_replay():
|
||||||
|
log = RunLog("test_run.log")
|
||||||
|
log.log({"event": "start"})
|
||||||
|
# Replay should yield 1+ entries; we simply verify that it yields a dict-like payload
|
||||||
|
entries = list(RunLog.replay("test_run.log"))
|
||||||
|
assert len(entries) >= 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_adapter_translation_and_governance_signing():
|
||||||
|
a1 = Asset(symbol="AAPL", kind="Equity")
|
||||||
|
strategy = StrategyDelta(delta_budget=10.0, vega_budget=2.0, gamma_budget=1.0, pnl_target=1.0,
|
||||||
|
assets=[a1])
|
||||||
|
# price feed translation
|
||||||
|
ms = MarketSignal(symbol="AAPL", price=150.0, liquidity=0.8, latency_proxy=0.02)
|
||||||
|
strategy.signals = [ms]
|
||||||
|
feeds = translate_market_signals(strategy)
|
||||||
|
assert "AAPL" in feeds
|
||||||
|
|
||||||
|
# plan delta translation
|
||||||
|
plan = PlanDelta(hedge_updates={"AAPL": 5.0}, authority="tester")
|
||||||
|
exec_map = translate_plan_delta(plan)
|
||||||
|
assert exec_map["AAPL"] == 5.0
|
||||||
|
|
||||||
|
# governance signing
|
||||||
|
signer = LedgerSigner("secretkey")
|
||||||
|
payload = plan.to_dict() if hasattr(plan, 'to_dict') else plan.__dict__
|
||||||
|
sig = signer.sign(str(payload))
|
||||||
|
assert signer.verify(str(payload), sig)
|
||||||
Loading…
Reference in New Issue