Ignore:
Timestamp:
09/16/26 23:37:15 (13 days ago)
Author:
Stefan <trsunovstefan@…>
Branches:
main
Children:
8b447ef
Parents:
df05838
Message:

add reserved_quantity and modify the phases, add v_03.png and v_03.xml for P1

File:
1 edited

Legend:

Unmodified
Added
Removed
  • docs/P4-Prototype/UseCase0004Implementation.md

    rdf05838 r9577c79  
    2727   BEGIN;
    2828
    29    -- (a) record the order
     29   -- (a) record the order as 'open' — no trade has happened yet
    3030   INSERT INTO orders
    31        (user_id, market_id, side, type, status, quantity, price, executed_at)
     31       (user_id, market_id, side, type, status, quantity, price)
    3232   VALUES
    33        ($1, $2, 'buy', 'market', 'executed', $3, $4, now())
     33       ($1, $2, 'buy', 'market', 'open', $3, $4)
    3434   RETURNING id;
    3535
    … …  
    3737   SELECT available_balance FROM users WHERE id = $1 FOR UPDATE;
    3838
    39    -- (c) move cash from available to invested
     39   -- (c) move cash from available to invested. A buy never reserves crypto
     40   --     the way a sell does (see UC0005) — it only ever adds to the
     41   --     position, so there is nothing to commit on the holdings side
     42   --     before settling.
    4043   UPDATE users
    4144      SET available_balance = available_balance - $notional,
    … …  
    4750   --     in one statement. Every SET expression sees the pre-update row, so
    4851   --     holdings.quantity below is still the old quantity.
     52   --     reserved_quantity is untouched by a buy and defaults to 0.
    4953   INSERT INTO holdings (user_id, crypto_id, quantity, avg_price, updated_at)
    5054   VALUES ($1, $c, $3, $4, now())
    … …  
    6872       ($2, now(), $4, $3, 'buy', 'user');
    6973
     74   -- (g) settle the order itself — it has now actually been filled
     75   UPDATE orders SET status = 'executed', executed_at = now() WHERE id = $orderId;
     76
    7077   COMMIT;
    7178   ```
    … …  
    7784## Verified run (from actual prototype execution)
    7885
    79 With seed data loaded:
     86Re-run 2026-09-16 against PostgreSQL 16 (`bp_database` on `localhost:5433`) with freshly loaded seed data:
    8087
    81 - **Before:** alice.available_balance = 8250.00, portfolio = { ETH: 0.5 }.
     88- **Before:** alice.available_balance = 8250.00, portfolio = { ETH: 0.5000, reserved 0.0000 }.
    8289- **Command:** `buy 0.01 BTC`.
    83 - **After:** alice.available_balance = 7578.60 (= 8250 − 671.40), portfolio = { BTC: 0.01 @ 67140, ETH: 0.5 @ 3500 }, net worth = 10010.00 USD (the +10 is the ETH unrealised P/L from the price moving from 3500 → 3520).
     90- **After:** alice.available_balance = 7578.60 (= 8250 − 671.40), portfolio = { BTC: 0.0100 @ 67140 (reserved 0.0000), ETH: 0.5000 @ 3500 (reserved 0.0000) }, net worth = 10010.00 USD (the +10 is the ETH unrealised P/L from the price moving from 3500 → 3520). A buy never sets `reserved_quantity`, so it reads 0 on every row here.
    8491
    8592## Failure path — insufficient funds
    8693
    87 If `available_balance < notional`, the `defer tx.Rollback()` in `server/trade.go` reverts all six statements and the user sees:
     94If `available_balance < notional`, the `defer tx.Rollback()` in `server/trade.go` reverts every statement above and the user sees:
    8895
    8996```
Note: See TracChangeset for help on using the changeset viewer.