Bird
Raised Fist0

Design an Online Stock Brokerage - Portfolio, Trade, Order, Market Data, P&L

LLDmediumInterview freq: medium
Choose your preparation mode4 modes available
๐ŸŽฏ
Design an Online Stock Brokerage - Portfolio, Trade, Order, Market Data, P&L
40 min ยท hard
hard

Design a system that supports multiple users managing portfolios with real-time market data, placing orders (market, limit), executing trades, and calculating P&L. The system must handle concurrent order submissions, maintain consistency of portfolio holdings, and provide accurate P&L updates.

  • Users can have multiple portfolios, each with multiple holdings of various stocks.
  • Orders can be market or limit orders and must be processed concurrently with thread safety.
  • Market data updates arrive asynchronously and must update portfolio valuations in real-time.
  • Trades update portfolio holdings and trigger P&L recalculations atomically.
  • The system must prevent race conditions on portfolio updates and ensure eventual consistency.
  • Pricing structure includes commissions per trade and fees that affect P&L.
๐Ÿ“‹
Guided Steps
1/5
Step 1
Define core domain entities and their relationships
Identify and design the main classes such as Portfolio, Holding, Order, Trade, MarketData, and PnL. Specify their relationships and ownership.
๐Ÿ’ก Hint
Use composition for Portfolio-Holding since holdings cannot exist without a portfolio. Use aggregation or association for MarketData since it can exist independently.
Use composition for Portfolio-Holding relationship to enforce lifecycle ownership; Holding instances cannot exist without Portfolio. Use aggregation for MarketData as it is shared and independent.
Mid: Names composition and aggregation relationships. Senior: Explains lifecycle ownership and why Holding must be composed to prevent dangling references.
โš ๏ธCommon Wrong Answer
Using association for Portfolio-Holding leads to Holding instances existing without Portfolio, causing stale or orphaned holdings and inconsistent portfolio state.
Step 2
Design Order and Trade classes with concurrency control
Design Order and Trade classes to handle concurrent order submissions and trade executions. Ensure thread-safe updates to portfolio holdings.
๐Ÿ’ก Hint
Use synchronized methods or locks on portfolio update methods to atomically check and update holdings. Consider volatile or AtomicInteger for status flags.
Use synchronized boolean executeTrade(Trade t) method in Portfolio class to atomically update holdings and PnL; use volatile status flags in Order class to ensure visibility across threads.
Mid: Identifies synchronized methods for atomic updates. Senior: Traces thread interleaving where without synchronized, two trades update holdings concurrently causing inconsistent state.
โš ๏ธCommon Wrong Answer
Not synchronizing portfolio updates causes race conditions where two threads read same holdings, update independently, and overwrite each other leading to incorrect holdings.
Step 3
Implement MarketData updates and real-time portfolio valuation
Design how MarketData updates asynchronously update portfolio valuations and PnL in a thread-safe manner.
๐Ÿ’ก Hint
Use observer pattern with thread-safe event dispatch. Use volatile or AtomicReference for latest price in MarketData. Portfolio valuation update methods must be synchronized or use concurrent data structures.
MarketData uses volatile double latestPrice field to ensure visibility; Portfolio subscribes via thread-safe observer pattern; synchronized updateValuation() method atomically recalculates holdings value and PnL.
Mid: Names observer pattern and volatile for price visibility. Senior: Explains how volatile prevents stale reads of latestPrice and synchronized prevents partial valuation updates.
โš ๏ธCommon Wrong Answer
Using non-volatile latestPrice causes threads to read stale prices, leading to incorrect PnL calculations and inconsistent portfolio valuations.
Step 4
Design PnL calculation and commission fee integration
Design PnL calculation that incorporates commissions and fees per trade, ensuring accurate and thread-safe updates.
๐Ÿ’ก Hint
Use an abstract class or interface for PnLCalculator to allow extensibility. Use synchronized methods to update PnL atomically after trade execution.
Implement PnLCalculator as an abstract class with synchronized updatePnL(Trade t) method to atomically add realized/unrealized PnL including commissions; interface cannot hold state so abstract class chosen.
Mid: Identifies abstract class for shared state and behavior. Senior: Explains why interface cannot hold commission state and synchronized update prevents race conditions on PnL updates.
โš ๏ธCommon Wrong Answer
Using interface for PnLCalculator leads to inability to hold commission state, forcing external mutable state and risking inconsistent PnL calculations.
Step 5
Ensure extensibility and SOLID compliance
Design the system to allow adding new order types or fee structures without modifying existing classes.
๐Ÿ’ก Hint
Use Open-Closed Principle by defining Order as abstract class or interface and extend for new types. Use Strategy pattern for fee calculation.
Define Order as abstract class with subclasses MarketOrder and LimitOrder to allow extension; implement FeeCalculator interface with multiple implementations injected via composition to follow Open-Closed Principle.
Mid: Names Open-Closed Principle and Strategy pattern. Senior: Explains how abstract class allows shared state and behavior, and composition avoids modifying existing code when adding fees.
โš ๏ธCommon Wrong Answer
Hardcoding fee logic inside Order violates Open-Closed Principle, requiring code changes for new fee types and risking regressions.
๐Ÿ”Œ
API Design Challenge
Design APIs that allow clients to submit orders, receive trade confirmations, and query portfolio valuations with real-time market data updates.
  • Use RESTful endpoints with WebSocket or Server-Sent Events for real-time updates.
  • Design idempotent order submission APIs to handle retries safely.
  • Include pagination and filtering for portfolio and trade history queries.
๐Ÿ“Š
Scoring Rubric
โ–ผ Show
Must Have - 60%
  • Composition relationship for Portfolio-Holding with lifecycle ownership
  • Synchronized methods for atomic portfolio updates
  • Volatile fields for shared mutable state visibility
  • Abstract class for PnLCalculator holding commission state
  • Observer pattern for MarketData updates
Good to Have - 30%
  • Strategy pattern for fee calculation extensibility
  • Abstract class hierarchy for Order types
  • Thread-safe event dispatch in MarketData
  • Atomic variables for status flags
Bonus - 10%
  • Use of Java concurrency utilities like AtomicInteger or ReentrantLock
  • Detailed explanation of lifecycle ownership and thread safety
โœ…
Model Answer
โ–ผ Reveal

The system design includes core domain entities such as Portfolio, Holding, Order, Trade, MarketData, and PnLCalculator. Portfolio owns Holdings via composition to enforce lifecycle. Orders and Trades use volatile status flags and synchronized methods to ensure thread-safe updates. MarketData uses volatile latestPrice and observer pattern for asynchronous updates. PnLCalculator is an abstract class with synchronized update methods to incorporate commissions and fees. The design follows SOLID principles with abstract Order classes and Strategy pattern for fee calculation to allow extensibility without modifying existing code.

  • Use composition for Portfolio-Holding to enforce lifecycle ownership and prevent orphan holdings
  • Use volatile fields in Order and MarketData to ensure visibility of shared mutable state across threads
  • Synchronize Portfolio methods that update holdings and PnL to prevent race conditions
  • Implement PnLCalculator as abstract class to hold commission state and synchronize updates
  • Apply observer pattern for MarketData to asynchronously notify Portfolios of price changes
  • Use abstract Order class and subclasses to allow adding new order types without modifying base code
  • Use Strategy pattern for fee calculation to enable extensible fee structures via composition
  • Portfolio-Holding composition enforces lifecycle ownership; Holding cannot exist independently.
  • Order and Trade classes use volatile status flags and synchronized methods to ensure thread-safe state transitions and portfolio updates.
  • MarketData uses volatile fields for latest prices and observer pattern with thread-safe event dispatch to update portfolios.
  • PnLCalculator implemented as abstract class to hold commission state and synchronized update methods to prevent race conditions.
  • Order hierarchy uses abstract class to hold shared state and behavior; new order types extend without modifying base classes.
  • Fee calculation uses Strategy pattern via interface and composition to allow extensible fee structures without code changes.
  • Synchronized portfolio update methods prevent race conditions where concurrent trades could corrupt holdings.
  • Volatile fields ensure visibility of shared mutable state across threads, preventing stale reads.
  • Observer pattern decouples MarketData updates from Portfolio valuation logic, enabling asynchronous updates.
  • Open-Closed Principle enforced by abstract classes and interfaces to allow system extension without modification.

Practice

(1/5)
1. In designing the Piece abstraction for the Jigsaw Puzzle System, should Piece be an abstract class or an interface? Consider that each piece has state (shape, edges) and behavior (fit check). Which is the best choice and why?
easy
A. Piece should be an interface because it only defines behavior, and state should be in implementations.
B. Piece should be an abstract class because it holds common state and default behavior for all pieces.
C. Piece should be a concrete class to allow direct instantiation and avoid subclassing complexity.
D. Piece should be a static utility class since pieces only need stateless helper methods.

Solution

  1. Step 1: Analyze state and behavior requirements

    Pieces share common state (shape, edges) and behavior (fit check), so code reuse and shared state management is needed.
  2. Step 2: Evaluate abstract class vs interface

    Abstract class allows holding common state and default behavior, while interface cannot hold state (pre-Java 8) and only defines contracts.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Abstract class holds shared state and behavior for Pieces [check]
Hint: State + behavior = abstract class, not interface [check]
Common Mistakes:
2. You want to add a WeekendFeeStrategy to calculate parking fees differently on weekends. According to SOLID principles, what is the minimum change required in the current Abstract Factory design?
medium
A. Add a boolean weekend flag to ParkingLot and modify fee calculation accordingly.
B. Create a new WeekendFeeStrategy class implementing FeeStrategy and inject it without modifying existing classes.
C. Combine all fee strategies into one class with multiple methods for each pricing rule.
D. Modify the existing FeeStrategy class to add weekend logic with if-else checks.

Solution

  1. Step 1: Identify SOLID principle involved

    Open-Closed Principle (OCP) requires new functionality added via extension, not modification.
  2. Step 2: Evaluate options

    Create a new WeekendFeeStrategy class implementing FeeStrategy and inject it without modifying existing classes. respects OCP by adding a new class without modifying existing ones. Add a boolean weekend flag to ParkingLot and modify fee calculation accordingly. modifies ParkingLot, violating OCP. Options A and D modify existing classes, violating OCP.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New strategy class added, existing classes unchanged [check]
Hint: OCP: extend with new class, don't modify existing ones [check]
Common Mistakes:
3. In a parking lot system, if parkVehicle() is not synchronized, which exact thread interleaving causes double-booking of the same spot?
medium
A. Thread 1 checks spot availability -> true, context switch; Thread 2 checks availability -> true; both park simultaneously.
B. Thread 1 parks vehicle, Thread 2 parks vehicle after Thread 1 finishes.
C. Thread 1 parks vehicle, Thread 2 waits for lock release before parking.
D. Thread 1 releases spot, Thread 2 immediately occupies it without checking.

Solution

  1. Step 1: Identify the check-then-act race condition

    Without synchronization, Thread 1 reads spot as available but before marking it occupied, context switches to Thread 2 which also reads available.
  2. Step 2: Both threads proceed to park, causing double-booking

    Both threads believe the spot is free and park simultaneously, violating mutual exclusion.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Check-then-act gap without synchronization -> double-booking [check]
Hint: Check availability -> context switch -> both park -> double-booking [check]
Common Mistakes:
4. The ESPNcricinfo system needs to support ElectricCar vehicles that require ChargingSpot parking spots. What is the minimum change to the current design to support this without modifying existing classes?
hard
A. Modify Vehicle class to add isElectric flag and add charging logic inside existing Spot classes.
B. Create a new ElectricCar class and ChargingSpot class, then modify ParkingLot to handle both types explicitly.
C. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar extends Vehicle, and update SpotCompatibility.COMPATIBILITY_MAP accordingly.
D. Add a new method in Vehicle interface for charging and implement it only in ElectricCar.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Adding new enum values and new subclasses allows extension without changing existing class code.
  2. Step 2: Update compatibility map for new types

    Updating SpotCompatibility.COMPATIBILITY_MAP supports new vehicle-spot matching without altering existing logic.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Extend enums + new subclasses + update compatibility map -> no existing class changes [check]
Hint: Extend enums + new subclasses + compatibility map -> minimal change [check]
Common Mistakes:
5. You need to add ElectricCar support with ChargingSpot in the parking system. What is the minimum change to the current design to support this without modifying existing classes?
hard
A. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType, create ElectricCar extending Vehicle, and update SpotCompatibility.COMPATIBILITY_MAP accordingly.
B. Modify Vehicle class to add a boolean isElectric and add charging logic inside existing methods.
C. Create a new ElectricVehicle interface and modify ParkingLot to handle it specially.
D. Add a god-class ElectricCarManager that handles all electric car logic separately.

Solution

  1. Step 1: Identify extensibility requirements

    Adding ElectricCar and ChargingSpot requires new types and compatibility rules without modifying existing classes to respect OCP and avoid class explosion.
  2. Step 2: Evaluate options

    Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType, create ElectricCar extending Vehicle, and update SpotCompatibility.COMPATIBILITY_MAP accordingly. adds new enum values and classes, updating compatibility map without changing existing code. Modify Vehicle class to add a boolean isElectric and add charging logic inside existing methods. modifies Vehicle class, violating OCP. Create a new ElectricVehicle interface and modify ParkingLot to handle it specially. adds interface but requires modifying ParkingLot, violating minimal change. Add a god-class ElectricCarManager that handles all electric car logic separately. creates god-class, violating SRP and maintainability.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    New enums + class + compatibility map update -> minimal change [check]
Hint: Add enums + class + map update, no existing class changes -> minimal [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard