62 lines
2.3 KiB
Python
62 lines
2.3 KiB
Python
from typing import Callable, List
|
|
from .contracts import QuoteSnapshot, OrderEvent
|
|
|
|
|
|
class ToyVenueAdapter:
|
|
"""A tiny in-process adapter that exposes a simple order acceptance model.
|
|
|
|
It accepts OrderEvent objects and updates an internal top-of-book. Deterministic
|
|
behaviour is achieved by not using random jitter and relying on caller ordering.
|
|
"""
|
|
|
|
def __init__(self, venue_id: str, initial_bid: float = 100.0, initial_ask: float = 100.5, asset: str = "TEST/USD"):
|
|
self.venue_id = venue_id
|
|
self.asset = asset
|
|
self.initial_bid = initial_bid
|
|
self.initial_ask = initial_ask
|
|
self.best_bid = initial_bid
|
|
self.best_ask = initial_ask
|
|
self.listeners: List[Callable[[QuoteSnapshot], None]] = []
|
|
|
|
def reset(self):
|
|
self.best_bid = self.initial_bid
|
|
self.best_ask = self.initial_ask
|
|
|
|
def _normalize_book(self):
|
|
if self.best_ask <= self.best_bid:
|
|
midpoint = (self.best_bid + self.best_ask) / 2
|
|
self.best_bid = round(midpoint - 0.005, 4)
|
|
self.best_ask = round(midpoint + 0.005, 4)
|
|
|
|
def on_snapshot(self, cb: Callable[[QuoteSnapshot], None]):
|
|
self.listeners.append(cb)
|
|
|
|
def publish_snapshot(self):
|
|
snap = QuoteSnapshot(
|
|
venue_id=self.venue_id,
|
|
asset=self.asset,
|
|
bids=[[self.best_bid, 100.0]],
|
|
asks=[[self.best_ask, 100.0]],
|
|
)
|
|
for cb in list(self.listeners):
|
|
cb(snap)
|
|
|
|
def handle_order(self, order: OrderEvent) -> OrderEvent:
|
|
# Very small deterministic matcher: marketable at top-of-book executes
|
|
impact = round(max(order.size, 1.0) * 0.05, 4)
|
|
if order.side == "buy" and order.price is None:
|
|
order.status = "filled"
|
|
self.best_bid = round(self.best_bid + impact, 4)
|
|
self.best_ask = round(self.best_ask + impact, 4)
|
|
self._normalize_book()
|
|
elif order.side == "sell" and order.price is None:
|
|
order.status = "filled"
|
|
self.best_bid = round(self.best_bid - impact, 4)
|
|
self.best_ask = round(self.best_ask - impact, 4)
|
|
self._normalize_book()
|
|
else:
|
|
order.status = "accepted"
|
|
# publish new snapshot deterministically
|
|
self.publish_snapshot()
|
|
return order
|