Files
fn_registry/dev/issues/0088f-trading-risk-capability-group-and-kill-switch.md
T

2.2 KiB

id, title, status, type, domain, scope, priority, depends, blocks, related, created, updated, tags
id title status type domain scope priority depends blocks related created updated tags
0088f Trading: capability group `risk` + kill_switch pendiente feature
trading
meta
multi-app alta
2026-05-17 2026-05-17

0088f — Trading: capability group risk + kill_switch

Status: pendiente Created: 2026-05-14 Type: feature Parent: 0088 Depends: 0088a Blocks: 0088h (live_runner no arranca sin esto)

Problema

Cualquier intent emitido por una Strategy debe pasar por un risk gate antes de tocar el broker. El kill_switch debe ser invocable desde CLI/cron/UI antes de que exista un broker live — fail-safe absoluto.

Piezas

  1. Funciones puras:
    • position_size_kelly_py_finance(edge, variance, bankroll, kelly_fraction).
    • position_size_fixed_risk_py_finance(stop_distance, risk_per_trade_pct, equity).
    • cap_max_loss_per_trade_py_finance(intent, stop_price, equity, max_loss_pct).
    • cap_exposure_py_finance(intent, current_exposure, exposure_limit).
    • filter_correlation_py_finance(intents, current_positions, correlation_matrix, max_corr).
    • apply_risk_pipeline_py_finance(intents, portfolio, risk_config) -> list[OrderIntent] (pipeline puro que compone las anteriores).
  2. Funcion impura halt_all_strategies_py_finance(reason):
    • Escribe flag halted=true en ~/.fn_state/trading_halt.json (o tabla system_state en ledger).
    • Notifica (telegram via 0061 si aplica).
    • Idempotente: re-llamar no falla.
  3. Funcion pura is_halted_py_finance(state_path) -> bool que el live_runner consulta cada ciclo.
  4. Funcion release_halt_py_finance(reason) (impura, escribe). Solo via CLI manual, NO via API.
  5. Tag risk. Pagina madre docs/capabilities/risk.md.
  6. Tests deterministicos sobre cada cap/filter.

Aceptacion

  • ./fn run halt_all_strategies deja el sistema en estado halted en frio (verificable con is_halted).
  • Cualquier intent que falle un cap retorna [] (no se emite), motivo logueado en operations.db del live_runner.
  • Kill_switch invocable sin que el live_runner este corriendo (state file persistente).

No-objetivos

  • Risk dinamico aprendido (eso es feature futura). Risk_config se lee de YAML.
  • UI para risk_config: editable a mano en YAML primero.