Convert live ticks to the display currency
Python · FastAPI · intermediate · modification
Dashboards were showing raw exchange-local prices; this converts every tick into the display currency before storing it. on_tick now awaits the FX rate and stores the converted quote as self.latest, and get_latest() returns that enriched quote. Verified against the feed by pushing ticks and confirming get_latest() returns the converted price.
A single hot instrument prints ticks in bursts far faster than one FX round-trip; _rates.get_rate() goes over the network with variable latency, so on_tick calls for the same instrument routinely overlap in flight.
Requirements
- The market-data feed calls on_tick for every incoming price tick on the instrument; dashboards read the current quote via get_latest().
- Each tick must be converted into the display currency using the FX rate, which is fetched over the network (an async call).
- self.latest must always reflect the most recently received tick: a slower earlier enrichment must never overwrite the result of a newer one.
Files touched
- app/marketdata/ticker.py
--- app/marketdata/ticker.py The market-data feed pushes a raw tick for the instrument on every price -change, and dashboards read the current quote via get_latest(). +change, and dashboards read the current display-currency quote via +get_latest(). Each tick is enriched before it is stored: the raw price is +converted into the display currency using the latest FX rate, which is +fetched over the network. get_latest() then returns that enriched quote. """ -from app.marketdata.models import Tick +from app.marketdata.models import Quote, Tick +from app.marketdata.rates import RatesClient + +DISPLAY_CURRENCY = "USD" class PriceTicker: - def __init__(self) -> None: - self.latest: Tick | None = None + def __init__(self, rates: RatesClient) -> None: + self._rates = rates + self.latest: Quote | None = None - def on_tick(self, tick: Tick) -> None: - self.latest = tick + async def _enrich(self, tick: Tick) -> Quote: + # Convert the raw price into the display currency. The FX rate is a + # network call, so this awaits. + rate = await self._rates.get_rate(tick.currency, DISPLAY_CURRENCY)