47 lines
1.9 KiB
Python
47 lines
1.9 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 = "option") -> Asset:
|
|
"""Lightweight helper to build a canonical Asset object for options.
|
|
|
|
Matches usage in tests which expect an option Asset constructed via
|
|
build_asset("AAPL_OPT"). 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 OptionsFeedAdapter:
|
|
"""Starter options market data adapter (stubbed for MVP).
|
|
|
|
Produces deterministic signals for options on two assets across two venues.
|
|
"""
|
|
|
|
def __init__(self, assets=None, venues=None):
|
|
self.assets = assets or [{"symbol": "AAPL", "type": "call"}, {"symbol": "MSFT", "type": "put"}]
|
|
self.venues = venues or ["VENUE-A", "VENUE-B"]
|
|
|
|
def stream_signals(self) -> Iterator[MarketSignal]:
|
|
t = datetime.utcnow()
|
|
for i in range(4):
|
|
for venue in self.venues:
|
|
for a in self.assets:
|
|
symbol = a.get("symbol")
|
|
price = 5.0 * (1 + i * 0.01)
|
|
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})
|
|
|
|
def get_signals(assets=None, venues=None) -> Iterator[MarketSignal]:
|
|
"""Backward-compatible helper to fetch signals from the options feed.
|
|
|
|
Returns an iterator of MarketSignal objects for use in tests and downstream flows.
|
|
"""
|
|
adapter = OptionsFeedAdapter(assets=assets, venues=venues)
|
|
return adapter.stream_signals()
|