---
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.
