build(agent): molt-x#ed374b iteration
This commit is contained in:
parent
ef6096a599
commit
644542c229
|
|
@ -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,17 @@
|
||||||
|
# DeltaForge MVP: Architectural Guide
|
||||||
|
|
||||||
|
Overview
|
||||||
|
- Purpose: A minimal, auditable cross-venue hedging engine for two assets across two venues.
|
||||||
|
- Scope: Core DSL sketches, two starter adapters, a tiny central curator, and a toy backtester.
|
||||||
|
|
||||||
|
Architecture sketch
|
||||||
|
- DSL: StrategyDelta, Asset, MarketSignal, PlanDelta (data classes with simple validation).
|
||||||
|
- Adapters: canonical signals from venue data translated to StrategyDelta objects.
|
||||||
|
- Coordinating layer: local risk solvers per venue + a central curator that enforces cross-venue constraints via aggregated signals (ADMM-lite style).
|
||||||
|
- Execution adapter: routes to venues with latency/fee metadata in the plan delta.
|
||||||
|
- Backtester: deterministic replay engine.
|
||||||
|
- Governance: tamper-evident logs; cryptographic tag placeholders.
|
||||||
|
|
||||||
|
How to contribution
|
||||||
|
- Run tests via test.sh; ensure deterministic behavior.
|
||||||
|
- Extend with new adapters, new assets, or richer DSL primitives.
|
||||||
31
README.md
31
README.md
|
|
@ -1,3 +1,32 @@
|
||||||
# deltaforge-real-time-cross-asset-strateg
|
# deltaforge-real-time-cross-asset-strateg
|
||||||
|
|
||||||
A novel, open-source engine that automatically synthesizes, validates, and executes hedging and arbitrage strategies across options, equities, and futures across multiple venues with ultra-low latency. It provides a concise DSL to declare strategy ob
|
DeltaForge MVP: Minimal, open-source engine for real-time cross-asset hedging across options and equities across two venues.
|
||||||
|
|
||||||
|
Overview
|
||||||
|
- A compact DSL to declare strategy objectives (risk budgets, PnL targets, liquidity constraints).
|
||||||
|
- Two starter adapters (equity feed and options market data).
|
||||||
|
- Lightweight, two-venue risk solvers with a central curator for cross-venue constraints.
|
||||||
|
- Minimal deterministic backtester and a toy execution adapter.
|
||||||
|
- MVP runs in a small two-asset, two-venue scenario demonstrating delta-hedges and cross-venue spreads.
|
||||||
|
|
||||||
|
What’s included
|
||||||
|
- Python package deltaforge_mvp with core DSL scaffolds and demo flow.
|
||||||
|
- Adapters: deltaforge_mvp/adapters/equity_feed.py, deltaforge_mvp/adapters/options_feed.py
|
||||||
|
- Venue coordination: deltaforge_mvp/coordination.py (ADMM-lite style coordination skeleton)
|
||||||
|
- Backtester: deltaforge_mvp/backtester.py
|
||||||
|
- Demo: deltaforge_mvp/demo.py (orchestrates a simple delta hedge across two venues)
|
||||||
|
- Tests: tests/test_demo.py
|
||||||
|
- Test script: test.sh
|
||||||
|
- Metadata: AGENTS.md (architecture guide) and READY_TO_PUBLISH placeholder
|
||||||
|
|
||||||
|
How to run (locally)
|
||||||
|
- Build and install: python -m build
|
||||||
|
- Run demo: python -m deltaforge_mvp.demo
|
||||||
|
- Run tests: bash test.sh
|
||||||
|
|
||||||
|
Note: This is a minimal, initial MVP skeleton intended to bootstrap discussion and future extension. It focuses on the core concepts with simple deterministic flows.
|
||||||
|
|
||||||
|
Usage notes:
|
||||||
|
- The MVP uses a tiny Python package deltaforge_mvp with a demo orchestrator and two starter adapters.
|
||||||
|
- To run the demo: python -m deltaforge_mvp.demo
|
||||||
|
- To execute tests: bash test.sh
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
"""DeltaForge MVP package init.
|
||||||
|
Expose lightweight APIs for a tiny cross-venue hedging engine scaffold.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .core import StrategyDelta, Asset, MarketSignal, PlanDelta # re-export for convenience
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
"""Starter equity feed adapter: emits simple price signals for an equity."""
|
||||||
|
from __future__ import annotations
|
||||||
|
import time
|
||||||
|
|
||||||
|
from deltaforge_mvp.core import Asset, MarketSignal
|
||||||
|
|
||||||
|
|
||||||
|
def generate_signal(symbol: str, price: float) -> MarketSignal:
|
||||||
|
asset = Asset(type="equity", symbol=symbol)
|
||||||
|
return MarketSignal(asset=asset, price=price, volatility=0.2, liquidity=1.0, timestamp=time.time())
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
"""Starter options feed adapter: emits option market signals."""
|
||||||
|
from __future__ import annotations
|
||||||
|
import time
|
||||||
|
|
||||||
|
from deltaforge_mvp.core import Asset, MarketSignal
|
||||||
|
|
||||||
|
|
||||||
|
def create_option_symbol(underlying: str, strike: float, expiry: str) -> Asset:
|
||||||
|
return Asset(type="option", underlying=underlying, strike=strike, expires=expiry)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_signal(underlying: str, strike: float, expiry: str, price: float) -> MarketSignal:
|
||||||
|
asset = Asset(type="option", underlying=underlying, strike=strike, expires=expiry)
|
||||||
|
return MarketSignal(asset=asset, price=price, volatility=0.25, liquidity=0.8, timestamp=time.time())
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
"""Deterministic replay backtester (toy) for MVP."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from deltaforge_mvp.core import PlanDelta
|
||||||
|
|
||||||
|
|
||||||
|
class Backtester:
|
||||||
|
def __init__(self, seed: int = 0):
|
||||||
|
self.seed = seed
|
||||||
|
|
||||||
|
def replay(self, plan: PlanDelta) -> dict:
|
||||||
|
# Very small deterministic stub: compute a fake PnL based on number of deltas and a seed
|
||||||
|
pnl = 0.0
|
||||||
|
for d in plan.deltas:
|
||||||
|
pnl += (d.delta * 0.5) # arbitrary scaling for demo
|
||||||
|
return {"pnl": pnl, "delta_count": len(plan.deltas), "seed": self.seed}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
"""ADMM-lite style coordination skeleton for cross-venue coherence."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from deltaforge_mvp.core import PlanDelta, StrategyDelta
|
||||||
|
|
||||||
|
|
||||||
|
class LocalRiskSolver:
|
||||||
|
def __init__(self, venue_name: str):
|
||||||
|
self.venue_name = venue_name
|
||||||
|
|
||||||
|
def propose(self, signals: List[StrategyDelta]) -> PlanDelta:
|
||||||
|
# Minimal heuristic: aggregate deltas and propose a single PlanDelta per venue
|
||||||
|
# In real system this would solve a convex program; here we pass through the deltas.
|
||||||
|
pd = PlanDelta(deltas=signals, venue=self.venue_name, author="local-solver")
|
||||||
|
return pd
|
||||||
|
|
||||||
|
|
||||||
|
class CentralCurator:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def enforce(self, plans: List[PlanDelta]) -> PlanDelta:
|
||||||
|
# Naive: merge all deltas into a single PlanDelta with combined deltas
|
||||||
|
merged = []
|
||||||
|
for p in plans:
|
||||||
|
merged.extend(p.deltas)
|
||||||
|
return PlanDelta(deltas=merged, venue=None, author="curator")
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Asset:
|
||||||
|
"""Canonical asset representation.
|
||||||
|
Example: {"type": "equity", "symbol": "AAPL"} or {"type": "option", "underlying": "AAPL", "strike": 150, "expires": "2026-12-17"}
|
||||||
|
"""
|
||||||
|
|
||||||
|
type: str # 'equity', 'option', 'future'
|
||||||
|
symbol: Optional[str] = None
|
||||||
|
underlying: Optional[str] = None
|
||||||
|
strike: Optional[float] = None
|
||||||
|
expires: Optional[str] = None
|
||||||
|
|
||||||
|
def canonical_id(self) -> str:
|
||||||
|
if self.type == "equity":
|
||||||
|
return f"EQ:{self.symbol}"
|
||||||
|
if self.type == "option":
|
||||||
|
return f"OP:{self.underlying}:{self.strike}:{self.expires}"
|
||||||
|
if self.type == "future":
|
||||||
|
return f"FU:{self.symbol or self.underlying}:{self.expires}"
|
||||||
|
return f"UNK:{self.symbol or 'UNDEF'}"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class MarketSignal:
|
||||||
|
"""Lightweight market signal used by adapters to convey prices, liquidity, etc."""
|
||||||
|
asset: Asset
|
||||||
|
price: float
|
||||||
|
volatility: float = 0.0
|
||||||
|
liquidity: float = 1.0
|
||||||
|
timestamp: float = 0.0
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class StrategyDelta:
|
||||||
|
"""Local decision block; describes intent to adjust hedges for an asset.
|
||||||
|
This is a light DSL-like structure that adapters translate into venue orders.
|
||||||
|
"""
|
||||||
|
asset: Asset
|
||||||
|
delta: float # directional hedge to apply (positive means buy delta exposure, etc.)
|
||||||
|
vega: float = 0.0
|
||||||
|
gamma: float = 0.0
|
||||||
|
target_pnl: Optional[float] = None
|
||||||
|
max_order_size: float = 1.0
|
||||||
|
timestamp: float = 0.0
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class PlanDelta:
|
||||||
|
"""Incremental hedges/adjustments with metadata for auditability."""
|
||||||
|
deltas: List[StrategyDelta]
|
||||||
|
confidence: float = 1.0
|
||||||
|
venue: Optional[str] = None
|
||||||
|
author: str = "system"
|
||||||
|
timestamp: float = 0.0
|
||||||
|
signature: Optional[str] = None # placeholder for cryptographic tag
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
"""Minimal demonstration orchestrating two venues with a delta hedge."""
|
||||||
|
from __future__ import annotations
|
||||||
|
import time
|
||||||
|
|
||||||
|
from deltaforge_mvp.core import Asset, MarketSignal, StrategyDelta, PlanDelta
|
||||||
|
from deltaforge_mvp.adapters.equity_feed import generate_signal as equity_signal
|
||||||
|
from deltaforge_mvp.adapters.options_feed import generate_signal as option_signal
|
||||||
|
from deltaforge_mvp.coordination import LocalRiskSolver, CentralCurator
|
||||||
|
from deltaforge_mvp.backtester import Backtester
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Define two assets: one equity, one option (simplified)
|
||||||
|
eq = Asset(type="equity", symbol="AAPL")
|
||||||
|
opt = Asset(type="option", underlying="AAPL", strike=150, expires="2026-12-17")
|
||||||
|
|
||||||
|
# Generate simple signals from two adapters (toy values)
|
||||||
|
s1 = MarketSignal(asset=eq, price=180.0, volatility=0.2, liquidity=1.0, timestamp=time.time())
|
||||||
|
s2 = option_signal(underlying="AAPL", strike=150, expiry="2026-12-17", price=5.0)
|
||||||
|
|
||||||
|
# Local hedging decisions (tiny delta values for demo)
|
||||||
|
d1 = StrategyDelta(asset=eq, delta=0.5, timestamp=time.time())
|
||||||
|
d2 = StrategyDelta(asset=opt, delta=-0.3, timestamp=time.time())
|
||||||
|
|
||||||
|
# Venue solvers
|
||||||
|
solver_a = LocalRiskSolver("Venue-A")
|
||||||
|
solver_b = LocalRiskSolver("Venue-B")
|
||||||
|
plan_a = solver_a.propose([d1])
|
||||||
|
plan_b = solver_b.propose([d2])
|
||||||
|
|
||||||
|
curator = CentralCurator()
|
||||||
|
merged_plan = curator.enforce([plan_a, plan_b])
|
||||||
|
|
||||||
|
backtester = Backtester(seed=42)
|
||||||
|
results = backtester.replay(merged_plan)
|
||||||
|
|
||||||
|
print("DeltaForge MVP Demo Results:")
|
||||||
|
print(results)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
[build-system]
|
||||||
|
requires = ["setuptools>=42", "wheel"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "deltaforge-mvp"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Minimal MVP scaffolding for DeltaForge cross-venue hedgingEngine"
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.8"
|
||||||
|
license = {text = "MIT"}
|
||||||
|
authors = [ { name = "DeltaForge MVP" } ]
|
||||||
|
dependencies = ["numpy"]
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "Running Python build and tests for DeltaForge MVP..."
|
||||||
|
python -m build >/dev/null 2>&1 || { echo "[build] failed"; exit 1; }
|
||||||
|
pytest -q || { echo "[tests] failed"; exit 1; }
|
||||||
|
echo "All tests passed."
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
import pytest
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Robust import in case pytest runs with a constrained PYTHONPATH
|
||||||
|
try:
|
||||||
|
from deltaforge_mvp.demo import main
|
||||||
|
except Exception:
|
||||||
|
# Fallback: load module directly from repo path
|
||||||
|
import importlib.util
|
||||||
|
import pathlib
|
||||||
|
repo_root = pathlib.Path(__file__).parents[1].resolve()
|
||||||
|
# Ensure repo root is on sys.path for dynamic import fallback
|
||||||
|
if str(repo_root) not in sys.path:
|
||||||
|
sys.path.insert(0, str(repo_root))
|
||||||
|
demo_path = repo_root / 'deltaforge_mvp' / 'demo.py'
|
||||||
|
spec = importlib.util.spec_from_file_location("deltaforge_mvp.demo", str(demo_path))
|
||||||
|
if spec is None or spec.loader is None:
|
||||||
|
raise ImportError("Could not load deltaforge_mvp.demo fallback module")
|
||||||
|
mod = importlib.util.module_from_spec(spec)
|
||||||
|
spec.loader.exec_module(mod) # type: ignore
|
||||||
|
main = mod.main
|
||||||
|
|
||||||
|
|
||||||
|
def test_demo_runs():
|
||||||
|
# Ensure the demo runs without raising
|
||||||
|
ret = main()
|
||||||
|
assert ret == 0
|
||||||
Loading…
Reference in New Issue