--- id: "0088h" title: "Trading: app `live_runner` (service, paper-first, broker real behind flag)" status: pendiente type: feature domain: - trading scope: multi-app priority: alta depends: [] blocks: [] related: [] created: 2026-05-17 updated: 2026-05-17 tags: [] --- # 0088h — Trading: app `live_runner` (service, paper-first, broker real behind flag) **Status:** pendiente **Created:** 2026-05-14 **Type:** feature **Parent:** 0088 **Depends:** 0088b, 0088c, 0088d, 0088e, 0088f, 0088g **Blocks:** 0088j (assertions consume execution log del runner) ## Problema Necesitamos un service de larga duracion que corra una o varias estrategias en vivo. Master debe estar siempre desplegable; un broker real introduce riesgo. Patron: live_runner mergea con paper-only activo; el adapter de broker real entra detras de feature flag OFF en `dev/feature_flags.json` (`live-broker-binance`, etc.) y se activa por commit explicito tras paper-trading estable. ## Piezas 1. App service `projects/trading/apps/live_runner/`. Tag `service`. 2. Config en YAML (`runner.yaml`): lista de `{strategy_id, params_path, broker_id, account_id, instruments[], schedule}`. 3. Bucle del runner (cada N segundos o evento): - `if is_halted(): sleep`. - Fetch fresh market snapshot via `market_data` group. - Cargar portfolio snapshot desde `portfolio_tracker`. - Llamar `Strategy.decide` (pura). - Aplicar `apply_risk_pipeline`. - Para cada intent superviviente: `broker.place_order` + persistir intent en `operations.db`. - Reconciliar fills cada ciclo. Discrepancia > epsilon → `halt_all_strategies(reason)`. - Emitir snapshot equity a `portfolio_tracker.equity_snapshots`. 4. Hooks: - Adapter broker resuelto por nombre (paper/binance/ib/alpaca). Brokers reales detras de feature flag OFF; intentar usarlos con flag OFF → error claro. - Cualquier excepcion no controlada → `halt_all_strategies` + notificacion. 5. Tabla `operations.db` propia del runner con `executions` y `intents` (motivos de drop por risk). 6. `e2e_checks`: - `build`, `smoke` (arranca con `broker_paper`, una strategy noop que emite 0 intents, 1 ciclo, sale OK). - `kill_switch`: con `halt_all_strategies` previo, el runner no emite ordenes. - `reconciliation`: ledger == broker_paper (siempre true para paper, pero el check existe). 7. Deploy target en `deploy_server` (paper-only inicial). ## Aceptacion - Runner corre en paper 7 dias seguidos sin incidentes (criterio de cierre fuera del codigo, en el run real). - Flag `live-broker-*` documentado en `dev/feature_flags.json` con `enabled: false`. - `e2e_checks` verde en CI. - `halt_all_strategies` desde CLI corta el flujo en < 1 ciclo. ## No-objetivos - Multi-runner / orquestacion de multiples runners (un solo proceso por ahora). - Estrategias adaptativas que cambian params en vivo.