---
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: ["0088b", "0088c", "0088d", "0088e", "0088f", "0088g"]
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.
