Design a lightweight stock trading service that lets users register, browse stocks with mock prices, place buy/sell orders, and track their holdings and order history. Focus on core flows and clean, extensible code. The system is in-memory and single-process.
Examples
Example 1 - Add stocks, show list, market & favorable limit buys, portfolios, history, and balances
TradingService trade = new TradingService();
add two stocks ACME@100 and ZETA@50
trade.addStock("ACME", 100);
trade.addStock("ZETA", 50);
show all stocks, return ["ACME 100","ZETA 50"]
trade.showStocks();
create user U1 with 10,000 cash
trade.addUser("U1", 10000);
check initial balance for U1, return 10000
trade.getAccountBalance("U1");
place MARKET BUY 20 ACME @ current 100, return FILLED
trade.submitOrder("U1","ACME","MARKET","BUY",20,0);
balance after fill (spent 2000), return 8000
trade.getAccountBalance("U1");
place LIMIT BUY 10 ZETA @ 60, since current price for ZETA is 50 (≤ 60), return FILLED
trade.submitOrder("U1","ZETA","LIMIT","BUY",10,60);
balance after second fill (spent 500), return 7500
trade.getAccountBalance("U1");
view holdings for U1, return ["ACME 20","ZETA 10"]
trade.viewStockHoldings("U1");
view orders for U1, return
["ACME BUY 20 MARKET FILLED",
"ZETA BUY 10 LIMIT FILLED"]
trade.viewOrders("U1");
Example 2 - Validations and OPEN: insufficient cash, sell without holdings, unfavorable buy limit
TradingService trade = new TradingService();
add AMZN@678
trade.addStock("AMZN", 678);
create user U2 with 1,500 cash
trade.addUser("U2", 1500);
check initial balance for U2, return 1500
trade.getAccountBalance("U2");
place MARKET BUY 3 AMZN needs 3×678=2034 (>1500), return REJECTED
trade.submitOrder("U2","AMZN","MARKET","BUY",3,0);
balance unchanged after REJECTED, return 1500
trade.getAccountBalance("U2");
place LIMIT BUY 2 AMZN @ 600; current price 678 > 600 so not favorable, cash sufficient, return OPEN
trade.submitOrder("U2","AMZN","LIMIT","BUY",2,600);
balance unchanged for OPEN (no fill), return 1500
trade.getAccountBalance("U2");
place MARKET SELL 1 AMZN with zero holdings, return REJECTED
trade.submitOrder("U2","AMZN","MARKET","SELL",1,0);
balance unchanged after REJECTED, return 1500
trade.getAccountBalance("U2");
view holdings for U2, return []
trade.viewStockHoldings("U2");
view orders for U2, return
["AMZN BUY 3 MARKET REJECTED",
"AMZN BUY 2 LIMIT OPEN",
"AMZN SELL 1 MARKET REJECTED"]
trade.viewOrders("U2");
Example 3 - Price updates, selling flows (FILLED/OPEN/REJECTED), final portfolio & history (with balances) - with auto-fill after price rises to 160
TradingService trade = new TradingService();
add ACME@90
trade.addStock("ACME", 90);
create user U3 with 10,000 cash
trade.addUser("U3", 10000);
check initial balance for U3, return 10000
trade.getAccountBalance("U3");
place MARKET BUY 50 ACME @ 90, cost 4500, return FILLED
trade.submitOrder("U3","ACME","MARKET","BUY",50,0);
balance after buy, return 5500
trade.getAccountBalance("U3");
update ACME price to 120
trade.addStock("ACME", 120);
show all stocks, return ["ACME 120"]
trade.showStocks();
place LIMIT SELL 20 ACME @ 110 when current is 120 (≥ 110), return FILLED at 120
trade.submitOrder("U3","ACME","LIMIT","SELL",20,110);
balance after selling 20 (added 2400), return 7900
trade.getAccountBalance("U3");
attempt LIMIT SELL 40 ACME @ 150 with only 30 remaining, return REJECTED
trade.submitOrder("U3","ACME","LIMIT","SELL",40,150);
balance unchanged after REJECTED, return 7900
trade.getAccountBalance("U3");
place LIMIT SELL 10 ACME @ 150; since current price is 120 < 150 and holdings sufficient, return OPEN
trade.submitOrder("U3","ACME","LIMIT","SELL",10,150);
balance unchanged for OPEN, return 7900
trade.getAccountBalance("U3");
place MARKET SELL 5 ACME @ current 120, return FILLED
trade.submitOrder("U3","ACME","MARKET","SELL",5,0);
balance after market sell (added 600), return 8500
trade.getAccountBalance("U3");
raise ACME price to 160; previously OPEN LIMIT SELL 10 @ 150 becomes FILLED at 160
trade.addStock("ACME", 160);
balance after auto-fill of open order (added 1600), return 10100
trade.getAccountBalance("U3");
show all stocks, return ["ACME 160"]
trade.showStocks();
view holdings for U3, return ["ACME 15"]
trade.viewStockHoldings("U3");
view orders for U3, return
["ACME BUY 50 MARKET FILLED",
"ACME SELL 20 LIMIT FILLED",
"ACME SELL 40 LIMIT REJECTED",
"ACME SELL 10 LIMIT FILLED",
"ACME SELL 5 MARKET FILLED"]
trade.viewOrders("U3");