--- id: "0088d" title: "Trading: app `portfolio_tracker` (ledger INSERT-only)" status: pendiente type: feature domain: - trading scope: app-scoped priority: alta depends: [] blocks: [] related: [] created: 2026-05-17 updated: 2026-05-17 tags: [] --- # 0088d — Trading: app `portfolio_tracker` (ledger INSERT-only) **Status:** pendiente **Created:** 2026-05-14 **Type:** feature **Parent:** 0088 **Depends:** 0088a **Blocks:** 0088c, 0088h ## Problema Necesitamos un ledger inmutable multi-account, multi-currency, multi-asset desde el dia 1 + UI minima para inspeccionarlo. Es la fuente de verdad del estado de cuentas; cualquier broker (paper o real) escribe contra este ledger. ## Piezas 1. App Go en `projects/trading/apps/portfolio_tracker/` (service + sqlite_api + Mantine UI). 2. Schema (en `migrations/*.sql`, aditivo): - `accounts` (id, label, currency_base, broker_kind, created_at). - `instruments` (id, symbol, kind, currency_quote). - `transactions` (id, account_id, instrument_id, ts, side, qty, price, fee, fee_currency, client_order_id, broker_fill_id, raw_json, source). **INSERT-only**, indice por `(account_id, ts)` y unique sobre `client_order_id`. - `equity_snapshots` (id, account_id, ts, equity_quote_currency, unrealized_pnl, realized_pnl_delta). - `valuation_marks` (id, instrument_id, ts, price, source). Marca de precio para valoracion. 3. Funciones puras del registry (no inline en la app): - `reduce_positions_from_transactions_py_finance(txs) -> list[Position]`. - `compute_realized_pnl_py_finance(txs) -> float`. - `compute_unrealized_pnl_py_finance(positions, marks) -> float`. - `compute_equity_py_finance(balance, positions, marks) -> float`. 4. API HTTP via sqlite_api/CRUD generator sobre las 5 tablas. Endpoint custom `/api/equity_curve?account_id=X`. 5. UI Mantine con @fn_library: - Lista de cuentas con balance + equity actual. - Detalle de cuenta: tabla de transactions, grafico equity curve, posiciones abiertas. - Form de transaction manual (para depositos/retiradas/ajustes que no vienen de broker). 6. `e2e_checks` en `app.md`: - `build_frontend`, `build_backend`, `smoke` (arranca puerto efimero + GET `/api/health`). - `ledger_immutable`: intenta UPDATE/DELETE sobre `transactions` y espera fallo (constraint trigger). - `reconciliation`: tras insertar N transactions sinteticas, `reduce_positions` retorna lo esperado. 7. Tag `service` en `app.md`. Tag de grupo `journal`/`trading`. ## Aceptacion - Ledger no permite UPDATE/DELETE de transactions (trigger SQLite). - Reconciliacion determinista: dadas las mismas transactions, mismo resultado de posiciones/balance/equity. - `fn doctor artefacts` y `fn doctor cpp-apps` (n/a aqui) sin errores. - App lanzable como service con `deploy_server` (no obligatorio para cerrar el issue, pero `app.md` debe declarar deploy target). ## No-objetivos - Integracion broker. Eso entra en 0088c. - Computo de impuestos/FIFO fiscal. Solo PnL operativo.