Changeset 9577c79 for docs/P4-Prototype/UseCase0004Implementation.md
- Timestamp:
- 09/16/26 23:37:15 (13 days ago)
- Branches:
- main
- Children:
- 8b447ef
- Parents:
- df05838
- File:
-
- 1 edited
-
docs/P4-Prototype/UseCase0004Implementation.md (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
docs/P4-Prototype/UseCase0004Implementation.md
rdf05838 r9577c79 27 27 BEGIN; 28 28 29 -- (a) record the order 29 -- (a) record the order as 'open' — no trade has happened yet 30 30 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) 32 32 VALUES 33 ($1, $2, 'buy', 'market', ' executed', $3, $4, now())33 ($1, $2, 'buy', 'market', 'open', $3, $4) 34 34 RETURNING id; 35 35 … … 37 37 SELECT available_balance FROM users WHERE id = $1 FOR UPDATE; 38 38 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. 40 43 UPDATE users 41 44 SET available_balance = available_balance - $notional, … … 47 50 -- in one statement. Every SET expression sees the pre-update row, so 48 51 -- holdings.quantity below is still the old quantity. 52 -- reserved_quantity is untouched by a buy and defaults to 0. 49 53 INSERT INTO holdings (user_id, crypto_id, quantity, avg_price, updated_at) 50 54 VALUES ($1, $c, $3, $4, now()) … … 68 72 ($2, now(), $4, $3, 'buy', 'user'); 69 73 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 70 77 COMMIT; 71 78 ``` … … 77 84 ## Verified run (from actual prototype execution) 78 85 79 With seed data loaded:86 Re-run 2026-09-16 against PostgreSQL 16 (`bp_database` on `localhost:5433`) with freshly loaded seed data: 80 87 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 }. 82 89 - **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. 84 91 85 92 ## Failure path — insufficient funds 86 93 87 If `available_balance < notional`, the `defer tx.Rollback()` in `server/trade.go` reverts all six statementsand the user sees:94 If `available_balance < notional`, the `defer tx.Rollback()` in `server/trade.go` reverts every statement above and the user sees: 88 95 89 96 ```
Note:
See TracChangeset
for help on using the changeset viewer.
