deltaforge-real-time-cross-.../deltaforge/adapters/equity_feed.py

53 lines
2.0 KiB
Python

from __future__ import annotations
from datetime import datetime, timedelta
from typing import Iterator
from ..dsl import MarketSignal, Asset
def build_asset(symbol: str, asset_class: str = "equity") -> Asset:
"""Lightweight helper to build a canonical Asset object.
Matches usage in tests which expect an equity Asset constructed via
build_asset("AAPL"). The Asset data model is flexible, so we store the
provided symbol and the asset_class as provided.
"""
return Asset(symbol=symbol, asset_class=asset_class)
class EquityFeedAdapter:
"""Starter equity price feed adapter (stubbed for MVP).
Generates deterministic MarketSignal data for two assets across two venues.
"""
def __init__(self, symbols=None, venues=None):
self.symbols = symbols or ["AAPL", "MSFT"]
self.venues = venues or ["VENUE-A", "VENUE-B"]
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}
t = datetime.utcnow()
for i in range(4):
for v_i, venue in enumerate(self.venues):
for sym in self.symbols:
price = base.get(sym, 100.0) * (1 + (i * 0.001) + (v_i * 0.0005))
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
def get_signals(symbols=None, venues=None) -> Iterator[MarketSignal]:
"""Backward-compatible helper to fetch signals from the equity feed.
Returns an iterator of MarketSignal objects for use in tests and downstream flows.
"""
adapter = EquityFeedAdapter(symbols=symbols, venues=venues)
return adapter.stream_signals()