Changes between Initial Version and Version 1 of UC0004


Ignore:
Timestamp:
09/24/26 13:50:14 (4 days ago)
Author:
231285
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • UC0004

    v1 v1  
     1= Use-case 0004 — Place market BUY order =
     2
     3'''Initiating actor:''' Trader
     4
     5'''Other actors:''' Market Simulator (indirect — supplies the current price via `market_trades`).
     6
     7A Trader buys a crypto asset at the current market price. The operation touches five tables (`orders`, `users`, `holdings`, `transactions`, `market_trades`) and must either all succeed or all roll back.
     8
     9== Scenario ==
     10
     11 1. Trader chooses "Place market BUY order".
     12 2. System lists the available markets with their latest price:
     13
     14{{{
     15SELECT m.id, c.symbol, m.quote_currency, COALESCE(lp.price, 0)
     16  FROM project.markets m
     17  JOIN project.crypto  c  ON c.id = m.crypto_id
     18  LEFT JOIN project.v_latest_prices lp ON lp.market_id = m.id
     19 WHERE m.is_active = true
     20 ORDER BY c.symbol;
     21}}}
     22
     23 3. Trader enters a market symbol, e.g. `ETH`.
     24 4. System resolves the market and looks up the latest price:
     25
     26{{{
     27SELECT m.id, c.id AS crypto_id, c.symbol, m.quote_currency
     28  FROM project.markets m
     29  JOIN project.crypto c ON c.id = m.crypto_id
     30 WHERE upper(c.symbol) = upper($1) AND m.is_active = true;
     31
     32SELECT price FROM project.v_latest_prices WHERE market_id = $2;
     33}}}
     34
     35 5. Trader enters a quantity.
     36 6. System computes notional = quantity × price, opens a transaction, and does:
     37
     38{{{
     39BEGIN;
     40
     41-- (a) record intent — no trade has happened yet.
     42INSERT INTO project.orders
     43    (user_id, market_id, side, type, status, quantity, price)
     44VALUES
     45    ($user_id, $market_id, 'buy', 'market', 'open', $qty, $price)
     46RETURNING id;  -- captured as $order_id
     47
     48-- (b) lock and check the user balance
     49SELECT available_balance FROM project.users WHERE id = $user_id FOR UPDATE;
     50-- abort if available_balance < notional
     51
     52-- (c) move cash from available to invested. A buy never reserves crypto
     53--     the way a sell does — it only ever adds to the position, so there
     54--     is nothing on the holdings side to commit before settling.
     55UPDATE project.users
     56   SET available_balance = available_balance - $notional,
     57       invested_balance  = invested_balance  + $notional,
     58       updated_at        = now()
     59 WHERE id = $user_id;
     60
     61-- (d) upsert holding with running weighted-average price:
     62SELECT quantity, avg_price
     63  FROM project.holdings
     64 WHERE user_id = $user_id AND crypto_id = $crypto_id
     65 FOR UPDATE;
     66
     67-- Either INSERT (new holding) or UPDATE (existing), computing
     68-- new_avg = (old_qty*old_avg + $qty*$price) / (old_qty + $qty)
     69
     70-- (e) ledger entry
     71INSERT INTO project.transactions
     72    (user_id, type, amount, currency, related_order, description)
     73VALUES
     74    ($user_id, 'buy', -$notional, 'USD', $order_id, 'Market buy ...');
     75
     76-- (f) record the resulting market trade
     77INSERT INTO project.market_trades
     78    (market_id, executed_at, price, quantity, side, source)
     79VALUES
     80    ($market_id, now(), $price, $qty, 'buy', 'user');
     81
     82-- (g) settle the order itself — it has now actually been filled.
     83UPDATE project.orders
     84   SET status = 'executed', executed_at = now()
     85 WHERE id = $order_id;
     86
     87COMMIT;
     88}}}
     89
     90 7. System confirms: `Order executed: buy 0.0100 BTC @ 67140.000000 (notional 671.4000 USD)`.
     91
     92=== Alternate flow 6a — insufficient funds ===
     93
     94If `available_balance < notional`, the entire transaction rolls back and system shows "Insufficient funds: need X, have Y."
     95
     96=== Alternate flow 4a — market not found ===
     97
     98If the entered symbol does not match any active market, system shows "market X not found" and returns to the authenticated menu without opening a transaction.