build(agent): new-agents-4#58ba63 iteration
This commit is contained in:
parent
c519cc58c6
commit
68c5a8454d
|
|
@ -17,6 +17,7 @@ __all__ = [
|
||||||
"OptionsFeedAdapter",
|
"OptionsFeedAdapter",
|
||||||
"ExecutionEngine",
|
"ExecutionEngine",
|
||||||
"Backtester",
|
"Backtester",
|
||||||
|
"RealTimeEngine",
|
||||||
]
|
]
|
||||||
|
|
||||||
from .dsl import Asset, MarketSignal, StrategyDelta, PlanDelta
|
from .dsl import Asset, MarketSignal, StrategyDelta, PlanDelta
|
||||||
|
|
@ -25,3 +26,4 @@ from .adapters.equity_feed import EquityFeedAdapter
|
||||||
from .adapters.options_feed import OptionsFeedAdapter
|
from .adapters.options_feed import OptionsFeedAdapter
|
||||||
from .execution import ExecutionEngine
|
from .execution import ExecutionEngine
|
||||||
from .backtester import Backtester
|
from .backtester import Backtester
|
||||||
|
from .rt_engine import RealTimeEngine
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import Iterator
|
from typing import Iterator
|
||||||
|
|
||||||
from ..dsl import MarketSignal
|
from ..dsl import MarketSignal, Asset
|
||||||
|
|
||||||
|
|
||||||
class EquityFeedAdapter:
|
class EquityFeedAdapter:
|
||||||
|
|
@ -17,10 +17,18 @@ class EquityFeedAdapter:
|
||||||
self.venues = venues or ["VENUE-A", "VENUE-B"]
|
self.venues = venues or ["VENUE-A", "VENUE-B"]
|
||||||
|
|
||||||
def stream_signals(self) -> Iterator[MarketSignal]:
|
def stream_signals(self) -> Iterator[MarketSignal]:
|
||||||
|
"""Yield deterministic MarketSignal objects compatible with deltaforge.dsl.MarketSignal.
|
||||||
|
|
||||||
|
Each signal carries the canonical Asset description as expected by the DSL.
|
||||||
|
"""
|
||||||
base = {"AAPL": 150.0, "MSFT": 300.0}
|
base = {"AAPL": 150.0, "MSFT": 300.0}
|
||||||
t = datetime.utcnow()
|
t = datetime.utcnow()
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
for v_i, venue in enumerate(self.venues):
|
for v_i, venue in enumerate(self.venues):
|
||||||
for sym in self.symbols:
|
for sym in self.symbols:
|
||||||
price = base.get(sym, 100.0) * (1 + (i * 0.001) + (v_i * 0.0005))
|
price = base.get(sym, 100.0) * (1 + (i * 0.001) + (v_i * 0.0005))
|
||||||
yield MarketSignal(asset_symbol=sym, venue=venue, price=float(price), timestamp=t + timedelta(seconds=i))
|
asset = Asset(symbol=sym, type="equity")
|
||||||
|
ts = float((t + timedelta(seconds=i)).timestamp())
|
||||||
|
venue_code = 0.0 if venue == "VENUE-A" else 1.0
|
||||||
|
sig = MarketSignal(asset=asset, price=float(price), timestamp=ts, meta={"venue": venue_code})
|
||||||
|
yield sig
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import Iterator
|
from typing import Iterator
|
||||||
|
|
||||||
from ..dsl import MarketSignal
|
from ..dsl import MarketSignal, Asset
|
||||||
|
|
||||||
|
|
||||||
class OptionsFeedAdapter:
|
class OptionsFeedAdapter:
|
||||||
|
|
@ -23,4 +23,7 @@ class OptionsFeedAdapter:
|
||||||
for a in self.assets:
|
for a in self.assets:
|
||||||
symbol = a.get("symbol")
|
symbol = a.get("symbol")
|
||||||
price = 5.0 * (1 + i * 0.01)
|
price = 5.0 * (1 + i * 0.01)
|
||||||
yield MarketSignal(asset_symbol=symbol, venue=venue, price=price, timestamp=t + timedelta(seconds=i))
|
asset = Asset(symbol=symbol, type=a.get("type", "call"))
|
||||||
|
ts = float((t + timedelta(seconds=i)).timestamp())
|
||||||
|
venue_code = 0.0 if venue == "VENUE-A" else 1.0
|
||||||
|
yield MarketSignal(asset=asset, price=float(price), timestamp=ts, meta={"venue": venue_code})
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from .adapters.equity_feed import EquityFeedAdapter
|
||||||
|
from .adapters.options_feed import OptionsFeedAdapter
|
||||||
|
from .core import Curator
|
||||||
|
from .coordinator import Coordinator
|
||||||
|
from .execution import ExecutionEngine
|
||||||
|
from .backtester import Backtester
|
||||||
|
from .dsl import MarketSignal, PlanDelta, StrategyDelta, Asset
|
||||||
|
|
||||||
|
|
||||||
|
class RealTimeEngine:
|
||||||
|
"""Minimal real-time cross-asset engine (MVP).
|
||||||
|
|
||||||
|
Streams signals from equity and options adapters, synthesizes a plan via the
|
||||||
|
curator, coordinates cross-venue coherence, and executes the plan. Also runs a
|
||||||
|
deterministic replay for testing purposes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
equity_symbols: List[str] | None = None,
|
||||||
|
option_assets: List[dict] | None = None,
|
||||||
|
venues: List[str] | None = None,
|
||||||
|
sample_window: int = 4):
|
||||||
|
self.equity_symbols = equity_symbols or ["AAPL", "MSFT"]
|
||||||
|
self.option_assets = option_assets or [{"symbol": "AAPL", "type": "call"}, {"symbol": "MSFT", "type": "put"}]
|
||||||
|
self.venues = venues or ["VENUE-A", "VENUE-B"]
|
||||||
|
self.sample_window = sample_window
|
||||||
|
|
||||||
|
# Adapters
|
||||||
|
self.equity_adapter = EquityFeedAdapter(symbols=self.equity_symbols, venues=self.venues)
|
||||||
|
self.option_adapter = OptionsFeedAdapter(assets=self.option_assets, venues=self.venues)
|
||||||
|
|
||||||
|
# Lightweight components
|
||||||
|
self.curator = Curator()
|
||||||
|
self.coordinator = Coordinator()
|
||||||
|
self.engine = ExecutionEngine()
|
||||||
|
self.bt = Backtester(initial_cash=100000.0)
|
||||||
|
|
||||||
|
def _collect_signals(self) -> List[MarketSignal]:
|
||||||
|
signals: List[MarketSignal] = []
|
||||||
|
eq_iter = self.equity_adapter.stream_signals()
|
||||||
|
opt_iter = self.option_adapter.stream_signals()
|
||||||
|
|
||||||
|
for _ in range(self.sample_window):
|
||||||
|
try:
|
||||||
|
s = next(eq_iter)
|
||||||
|
signals.append(s)
|
||||||
|
except StopIteration:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
s = next(opt_iter)
|
||||||
|
signals.append(s)
|
||||||
|
except StopIteration:
|
||||||
|
pass
|
||||||
|
return signals
|
||||||
|
|
||||||
|
def run_cycle(self) -> dict:
|
||||||
|
"""Run a single deterministic cycle: collect signals, synthesize and coordinate a plan, and execute."""
|
||||||
|
signals = self._collect_signals()
|
||||||
|
# Build simple objectives from signals
|
||||||
|
objectives: List[StrategyDelta] = []
|
||||||
|
for idx, sig in enumerate(signals):
|
||||||
|
asset = sig.asset
|
||||||
|
hedges = 0.5 # simple heuristic placeholder
|
||||||
|
objectives.append(StrategyDelta(id=f"rt-{idx}", assets=[asset], hedge_ratio=hedges, target_pnl=0.0, constraints=[]))
|
||||||
|
|
||||||
|
# Curate a plan from signals (optional in MVP) – we keep this lightweight
|
||||||
|
plan_curated: PlanDelta = self.curator.synthesize_plan(signals, objectives)
|
||||||
|
|
||||||
|
# Cross-venue coordination step (ADMM-lite)
|
||||||
|
plan = self.coordinator.coordinate(signals, author="rt-engine")
|
||||||
|
|
||||||
|
# Execute plan (routing and PnL proxy)
|
||||||
|
exec_result = self.engine.execute(plan)
|
||||||
|
|
||||||
|
# Backtest replay for deterministic evaluation
|
||||||
|
replay = self.bt.run(plan)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"plan": plan,
|
||||||
|
"execution": exec_result,
|
||||||
|
"replay": replay,
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue