Process a Mutable Stock-Price Log
Lead BankSoftware Engineer · OnsiteLast updated
Design an in-memory mutable stock price log that supports recording prices, tracking update history, calculating percentage changes across dates, and comparing performance between tickers.
Problem Statement
Financial ledgers frequently ingest updates, corrections, and queries for market data. Design a class StockPriceTracker that maintains a mutable log of stock closing prices across various dates.
Dates are provided as opaque string identifiers (e.g., "2023-10-01", "D1"). Do not assume any chronological ordering based on lexicographical string order; each date should be treated strictly as a unique identifier.
Implement the following methods:
-
record_price(ticker: str, date: str, price: float) -> NoneRecords a price for a given ticker on a specified date. If a price already exists for that(ticker, date)pair, update it to the new price and preserve the record of previous values (update provenance). -
get_price(ticker: str, date: str) -> float | NoneReturns the current price for the given ticker on the specified date, orNoneif no price has been recorded. -
get_history(ticker: str, date: str) -> list[float]Returns the complete history of values recorded for the given(ticker, date)pair in the order they were submitted. If no entry exists, return an empty list. -
get_pct_change(ticker: str, date_from: str, date_to: str) -> str | NoneCalculates the percentage change fromdate_fromtodate_tousing the latest recorded prices:((price_to - price_from) / price_from) * 100. Return the result formatted as a string rounded to two decimal places with a%suffix (e.g.,"+5.25%"for positive,"-3.10%"for negative, or"0.00%"for zero). If either date has no recorded price or ifprice_fromis0, returnNone. -
compare_tickers(ticker_a: str, ticker_b: str, date_from: str, date_to: str) -> str | NoneCompares the percentage change ofticker_aagainstticker_bacross the same two dates.- Returns
ticker_aifticker_ahad a strictly greater percentage change. - Returns
ticker_bifticker_bhad a strictly greater percentage change. - Returns
"TIE"if both percentage changes are equal. - Returns
Noneif either ticker cannot calculate a valid percentage change.
- Returns
Example
tracker = StockPriceTracker()
tracker.record_price("AAPL", "2023-01-01", 100.0)
tracker.record_price("AAPL", "2023-01-02", 110.0)
tracker.record_price("MSFT", "2023-01-01", 200.0)
tracker.record_price("MSFT", "2023-01-02", 210.0)
# AAPL changed +10.00%, MSFT changed +5.00%
assert tracker.get_pct_change("AAPL", "2023-01-01", "2023-01-02") == "+10.00%"
assert tracker.get_pct_change("MSFT", "2023-01-01", "2023-01-02") == "+5.00%"
assert tracker.compare_tickers("AAPL", "MSFT", "2023-01-01", "2023-01-02") == "AAPL"
# Update AAPL price for 2023-01-02 to 95.0
tracker.record_price("AAPL", "2023-01-02", 95.0)
assert tracker.get_history("AAPL", "2023-01-02") == [110.0, 95.0]
assert tracker.get_pct_change("AAPL", "2023-01-01", "2023-01-02") == "-5.00%"
assert tracker.compare_tickers("AAPL", "MSFT", "2023-01-01", "2023-01-02") == "MSFT"
Constraints
- Number of total operations: up to
200,000. price >= 0.0for all record operations.- Ticker names and date identifiers are non-empty ASCII strings of length
1 <= len <= 32. - All query operations (
get_price,get_history,get_pct_change,compare_tickers) should run inO(1)average time.
Hints
Hint 1
Use a nested dictionary mapping each ticker to a dictionary of date keys, where each date maps to a list tracking the chronological sequence of price updates.
Hint 2
Be careful with floating-point formatting: ensure positive values include an explicit `+` sign and `0` renders as `0.00%` rather than `+0.00%` or `-0.00%`.
Hint 3
When comparing percentage changes between two tickers, compare the raw floating-point delta values rather than comparing formatted string outputs to avoid rounding discrepancies.
Follow-up questions
- How would you support rollbacks or time-travel queries (e.g., query what a ticker's price was as of operation timestamp T)?
- How would you handle concurrent reads and writes safely without introducing significant lock contention?
- If the dates were actual timestamps and we needed range queries (e.g., maximum price or average price between date A and date B), how would you adapt the internal data structure?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.