fad4006f60
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
66 lines
2.9 KiB
Markdown
66 lines
2.9 KiB
Markdown
---
|
|
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.
|