build(agent): new-agents-4#58ba63 iteration
This commit is contained in:
parent
4028ae6868
commit
c4004abdea
|
|
@ -0,0 +1,2 @@
|
|||
DeltaForge MVP scaffold for real-time cross-venue hedging across assets.
|
||||
This repository provides core DSL primitives, a minimal ADMM-like coordinator, two starter adapters, a toy backtester, and a test harness.
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
"""
|
||||
DeltaForge MVP: Core package initialization.
|
||||
"""
|
||||
from .dsl import StrategyDelta, Asset, MarketSignal, PlanDelta
|
||||
from .coordinator import Coordinator
|
||||
|
||||
__all__ = ["StrategyDelta", "Asset", "MarketSignal", "PlanDelta", "Coordinator"]
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
from __future__ import annotations
|
||||
import time
|
||||
from typing import List
|
||||
from ..dsl import Asset, MarketSignal
|
||||
|
||||
class EquityFeedAdapter:
|
||||
"""
|
||||
Starter equity feed adapter.
|
||||
In a real system this would connect to a streaming data source.
|
||||
Here we provide a deterministic, test-friendly generator.
|
||||
"""
|
||||
def __init__(self, asset_symbol: str = "AAPL"):
|
||||
self.asset = Asset(id="eq-"+asset_symbol, type="equity", symbol=asset_symbol)
|
||||
self.start = time.time()
|
||||
|
||||
def poll_signals(self) -> List[MarketSignal]:
|
||||
t = time.time() - self.start
|
||||
price = 150.0 + (t % 5) # deterministic-ish
|
||||
return [MarketSignal(asset=self.asset, timestamp=t, price=price, liquidity=1.0)]
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
from __future__ import annotations
|
||||
import time
|
||||
from typing import List
|
||||
from ..dsl import Asset, MarketSignal
|
||||
|
||||
class OptionsFeedAdapter:
|
||||
"""
|
||||
Starter options feed adapter (toy).
|
||||
"""
|
||||
def __init__(self, symbol: str = "AAPL-20260120-150C"):
|
||||
self.asset = Asset(id="opt-"+symbol, type="option", symbol=symbol)
|
||||
self.start = time.time()
|
||||
|
||||
def poll_signals(self) -> List[MarketSignal]:
|
||||
t = time.time() - self.start
|
||||
price = 5.0 + (t % 1.5)
|
||||
return [MarketSignal(asset=self.asset, timestamp=t, price=price, liquidity=1.0)]
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
from __future__ import annotations
|
||||
from typing import List
|
||||
from .dsl import MarketSignal, PlanDelta
|
||||
|
||||
class Backtester:
|
||||
"""
|
||||
Tiny deterministic replay engine.
|
||||
Applies PlanDelta actions to a simple PnL model.
|
||||
"""
|
||||
def __init__(self, initial_cash: float = 100000.0):
|
||||
self.cash = initial_cash
|
||||
self.positions: List[dict] = []
|
||||
|
||||
def apply(self, signals: List[MarketSignal], plan: PlanDelta) -> float:
|
||||
# Very simple PnL: sum(action.size * current_price) and adjust cash
|
||||
pnl = 0.0
|
||||
for act in plan.delta:
|
||||
symbol = act.get("symbol") or act.get("asset") or "UNKNOWN"
|
||||
size = act.get("size", 0.0)
|
||||
price = act.get("price") or act.get("premium") or 0.0
|
||||
if price is None:
|
||||
price = 0.0
|
||||
pnl += size * price
|
||||
self.positions.append({"symbol": symbol, "size": size, "price": price})
|
||||
self.cash += pnl
|
||||
return self.cash
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
from __future__ import annotations
|
||||
from typing import List
|
||||
from .dsl import MarketSignal, PlanDelta
|
||||
|
||||
class Coordinator:
|
||||
"""
|
||||
Lightweight ADMM-like coordinator.
|
||||
It collects MarketSignals from multiple venues and emits a PlanDelta
|
||||
representing a synchronized hedging action.
|
||||
This is a minimal, deterministic stub suitable for MVP testing.
|
||||
"""
|
||||
def __init__(self, contract_id: str = "default-contract"):
|
||||
self.contract_id = contract_id
|
||||
self.last_plan: PlanDelta | None = None
|
||||
|
||||
def coordinate(self, signals: List[MarketSignal], author: str = "coordinator") -> PlanDelta:
|
||||
# Very small heuristic: if two assets present, generate a delta-neutral hedge
|
||||
actions: List[dict] = []
|
||||
# Simple rule: create a hedge adjustment based on price relative to last plan
|
||||
for s in signals:
|
||||
if s.asset.type == "equity":
|
||||
actions.append({"action": "hedge", "symbol": s.asset.symbol, "size": -0.5, "price": s.price, "ts": s.timestamp})
|
||||
elif s.asset.type == "option":
|
||||
actions.append({"action": "adjust", "symbol": s.asset.symbol, "size": -0.25, "premium": s.price, "ts": s.timestamp})
|
||||
plan = PlanDelta(delta=actions, timestamp=signals[0].timestamp if signals else 0.0, author=author, contract_id=self.contract_id)
|
||||
self.last_plan = plan
|
||||
return plan
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
from __future__ import annotations
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Optional, Any
|
||||
|
||||
def _validate_non_empty(name: str, value: Any) -> None:
|
||||
if value is None or (isinstance(value, (str, list, dict)) and len(value) == 0):
|
||||
raise ValueError(f"{name} must be non-empty")
|
||||
|
||||
@dataclass
|
||||
class Asset:
|
||||
id: str
|
||||
type: str # "equity" | "option" | "future"
|
||||
symbol: str
|
||||
|
||||
def __post_init__(self):
|
||||
_validate_non_empty("Asset.id", self.id)
|
||||
_validate_non_empty("Asset.type", self.type)
|
||||
_validate_non_empty("Asset.symbol", self.symbol)
|
||||
|
||||
@dataclass
|
||||
class MarketSignal:
|
||||
asset: Asset
|
||||
timestamp: float
|
||||
price: float
|
||||
liquidity: float = 1.0
|
||||
extra: dict = field(default_factory=dict)
|
||||
|
||||
def __post_init__(self):
|
||||
_validate_non_empty("MarketSignal.asset", self.asset)
|
||||
if self.timestamp is None or self.price is None:
|
||||
raise ValueError("MarketSignal timestamp/price required")
|
||||
|
||||
@dataclass
|
||||
class PlanDelta:
|
||||
delta: List[dict] # A list of actions, simplified
|
||||
timestamp: float
|
||||
author: str
|
||||
contract_id: Optional[str] = None
|
||||
privacy_budget: Optional[dict] = None
|
||||
|
||||
def __post_init__(self):
|
||||
_validate_non_empty("PlanDelta.delta", self.delta)
|
||||
if self.timestamp is None:
|
||||
raise ValueError("PlanDelta.timestamp required")
|
||||
|
||||
@dataclass
|
||||
class StrategyDelta:
|
||||
id: str
|
||||
assets: List[Asset]
|
||||
objectives: dict
|
||||
constraints: dict = field(default_factory=dict)
|
||||
version: int = 1
|
||||
|
||||
def __post_init__(self):
|
||||
_validate_non_empty("StrategyDelta.id", self.id)
|
||||
_validate_non_empty("StrategyDelta.assets", self.assets)
|
||||
if not isinstance(self.assets, list) or len(self.assets) == 0:
|
||||
raise ValueError("StrategyDelta.assets must be a non-empty list")
|
||||
|
|
@ -1,13 +1,10 @@
|
|||
[build-system]
|
||||
requires = ["setuptools>=42", "wheel"]
|
||||
requires = ["setuptools", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "deltaforge-mvp"
|
||||
version = "0.1.0"
|
||||
description = "Minimal MVP scaffolding for DeltaForge cross-venue hedgingEngine"
|
||||
name = "deltaforge"
|
||||
version = "0.0.1"
|
||||
description = "MVP: cross-venue hedging engine scaffold"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.8"
|
||||
license = {text = "MIT"}
|
||||
authors = [ { name = "DeltaForge MVP" } ]
|
||||
dependencies = ["numpy"]
|
||||
requires-python = ">=3.9"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name="deltaforge",
|
||||
version="0.0.1",
|
||||
description="MVP: cross-venue hedging engine scaffold",
|
||||
packages=find_packages(include=["deltaforge", "deltaforge.*"]),
|
||||
include_package_data=True,
|
||||
install_requires=[],
|
||||
)
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import sys, os
|
||||
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
if ROOT not in sys.path:
|
||||
sys.path.insert(0, ROOT)
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
from deltaforge.backtester import Backtester
|
||||
from deltaforge.dsl import Asset, MarketSignal
|
||||
from deltaforge.dsl import PlanDelta
|
||||
|
||||
def test_backtester_runs_deterministic():
|
||||
a = Asset(id="eq-XYZ", type="equity", symbol="XYZ")
|
||||
s = MarketSignal(asset=a, timestamp=0.0, price=10.0)
|
||||
plan = PlanDelta(delta=[{"action": "hedge", "symbol": "XYZ", "size": -1.0, "price": 10.0}], timestamp=0.0, author="tester")
|
||||
bt = Backtester(initial_cash=1000.0)
|
||||
final_cash = bt.apply([s], plan)
|
||||
assert final_cash == 1000.0 - 1.0 * 10.0 + 0 # initial cash minus hedge cost
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
from deltaforge.coordinator import Coordinator
|
||||
from deltaforge.dsl import Asset, MarketSignal
|
||||
|
||||
def test_coordinator_creates_plan_delta():
|
||||
a1 = Asset(id="eq-XYZ", type="equity", symbol="XYZ")
|
||||
a2 = Asset(id="eq-ABC", type="equity", symbol="ABC")
|
||||
s1 = MarketSignal(asset=a1, timestamp=1.0, price=10.0)
|
||||
s2 = MarketSignal(asset=a2, timestamp=1.1, price=20.0)
|
||||
c = Coordinator(contract_id="test-contract")
|
||||
plan = c.coordinate([s1, s2], author="tester")
|
||||
assert plan is not None
|
||||
assert plan.contract_id == "test-contract"
|
||||
assert isinstance(plan.delta, list)
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import math
|
||||
from deltaforge.dsl import Asset, MarketSignal, PlanDelta, StrategyDelta
|
||||
|
||||
def test_asset_and_signals_creation():
|
||||
a = Asset(id="eq-ABC", type="equity", symbol="ABC")
|
||||
ms = MarketSignal(asset=a, timestamp=1.0, price=100.0)
|
||||
assert a.symbol == "ABC"
|
||||
assert ms.asset.symbol == "ABC"
|
||||
assert ms.price == 100.0
|
||||
|
||||
def test_plan_delta_creation():
|
||||
a = Asset(id="eq-ABC", type="equity", symbol="ABC")
|
||||
ms = MarketSignal(asset=a, timestamp=1.0, price=100.0)
|
||||
plan = PlanDelta(delta=[{"action": "hedge", "symbol": "ABC", "size": -0.5, "price": 100.0}], timestamp=1.0, author="tester")
|
||||
assert isinstance(plan.delta, list)
|
||||
assert plan.author == "tester"
|
||||
assert plan.timestamp == 1.0
|
||||
|
||||
def test_strategy_delta_creation():
|
||||
a = Asset(id="eq-ABC", type="equity", symbol="ABC")
|
||||
sd = StrategyDelta(id="s1", assets=[a], objectives={"maximize": "return"})
|
||||
assert sd.assets[0].symbol == "ABC"
|
||||
Loading…
Reference in New Issue