🛡️ sandbox-labs GitHub ↗

CM-05 · Intermediación financiera#

En una frase, para cualquiera: cuando compras algo a través de un intermediario, hay dos posibilidades muy distintas: que salga a buscarlo por ti, o que te lo venda de lo que él ya tenía. En la segunda, sus intereses y los tuyos apuntan en direcciones opuestas.

Estado real: 🟠 prototype — hay código y escenarios que se ejecutan, sin verificación en un entorno real · Módulo: crates/sandbox-markets/src/cases/intermediation.rs

Operaciones, inventario y clientes simulados. No es una autorización regulatoria ni una recomendación de inversión.

Por qué se realiza este caso#

La distinción entre agente y principal es la que más consecuencias tiene y la que peor se explica al cliente:

Como agenteComo principal
Qué haceBusca en el mercado por tiTe vende de su propio inventario
De dónde ganaComisión, explícitaDiferencia de precio (spread), casi nunca visible
Su interésAlineado contigoOpuesto: cuanto peor tu precio, mejor su margen
Qué debe declararLa comisiónQue actúa por cuenta propia

De ahí salen las conductas que este caso detecta:

ConductaQué es
Front-runningEjecutar la orden propia antes que la del cliente, sabiendo que la del cliente moverá el precio
Ejecución propia prioritariaLa orden de la casa se cuela delante en la cola
Comisión no informadaEl cliente no supo lo que pagaba
Confirmación falsaSe confirma una ejecución que no ocurrió como se dice
Venta sin disponibilidadSe vende algo que no se tiene ni se ha asegurado

La idea que enseña, y que ningún otro caso enseña#

El conflicto de interés es estructural, no moral. No depende de que alguien sea deshonesto: depende de en qué papel actúa. Por eso el control no es un código de conducta, es la trazabilidad del papel en cada operación y la comparación de tiempos entre la orden del cliente y la de la casa.

Casos de uso reales#

Cómo funcionará#

flowchart LR
  C["👤 Orden del cliente"] --> R{"🎭 ¿En qué papel<br/>se actúa?"}
  R -->|"agente"| A["🔍 Buscar en el mercado<br/>+ comisión declarada"]
  R -->|"principal"| P["📦 Vender del inventario<br/>+ spread declarado"]
  A --> E["✅ Ejecución"]
  P --> E
  E --> D["🕵️ Detección de conductas"]
  H["🏢 Órdenes de la casa"] --> D
  D --> F["🚨 Hallazgos"]
sequenceDiagram
  participant C as Cliente
  participant B as Intermediario
  participant M as Mercado
  C->>B: orden de compra grande (t=0)
  Note over B: sabe que moverá el precio
  B->>M: orden PROPIA de compra (t=1) ⚠️
  B->>M: orden del cliente (t=2)
  Note over B,M: el cliente compra más caro<br/>por culpa de la orden previa
  B-->>C: 🚨 front-running detectado por comparación de tiempos

Esquemas#

{
  "execution": {
    "clientOrderId": "cli-100",
    "capacity": "principal",
    "price": { "minorUnits": 10250, "currency": "CLP" },
    "referencePrice": { "minorUnits": 10200, "currency": "CLP" },
    "spread": { "minorUnits": 50, "currency": "CLP" },
    "commission": { "minorUnits": 0, "currency": "CLP" },
    "disclosedToClient": true
  }
}
{
  "findings": [
    { "kind": "FrontRunning", "houseOrder": "casa-9", "clientOrder": "cli-100", "deltaMs": 40, "priceImpact": 50 },
    { "kind": "UndisclosedCommission", "clientOrder": "cli-101" }
  ]
}

Software necesario#

ComponentePara qué
Rust 1.75+Motor de operaciones y detección de conductas
Node.js 20+ / pnpm 9+Panel (opcional)

Sin jaula ni Linux: lógica determinista sobre operaciones simuladas.

Instalación#

cargo build --release

Procesos que se crearán#

sandboxctl markets intermediation --scenario front-running
  │
  └─ un proceso determinista
      ├─ reloj simulado con marcas de secuencia
      └─ libro de partida doble para comisiones y spread

Tiempo de carga estimado#

OperaciónCoste esperado
Un escenario de conducta< 100 ms
Analizar 100 000 operacionessegundos

Qué hace falta para construirlo#

  1. Modelo de operación con capacity (agente/principal) obligatorio.
  2. Inventario propio, separado del de clientes (CM-03).
  3. Detección por comparación temporal entre órdenes de casa y de cliente.
  4. Declaración obligatoria de comisión y spread al cliente.
  5. Los cinco escenarios de conducta listados arriba.

Si algo falla#

El caso ya tiene código y escenarios que se ejecutan. Lo que sigue son sus fallos con la causa y la salida:

SituaciónCausaCómo se resuelve
Aparece FrontRunning en operaciones legítimasLa detección es temporal y puede dar falsos positivosSe revisa a mano con la reconstrucción del libro. La alerta trae deltaMs y priceImpact para poder juzgar, no un veredicto
Una operación no tiene capacityEl campo es obligatorioSin saber si se actuó como agente o como principal no se puede evaluar nada. Se rechaza el registro incompleto
El cliente no vio la comisióndisclosedToClient: falseEs UndisclosedCommission, y es un incumplimiento. Se corrige informando y dejando constancia de cuándo se informó
El inventario propio se mezcla con el de clientesFallo de segregaciónEs un hallazgo de CM-03, y es más grave que cualquier conducta de este caso

Los fallos que afectan a cualquier caso —la compilación, el catálogo, la evidencia— están resueltos uno a uno en Cuando algo falla.

Esta familia no necesita aislamiento del sistema: no ejecuta código ajeno, sino reglas de negocio deterministas. Por eso casi ningún fallo suyo viene del entorno, y casi todos vienen de los datos.

Cómo se comprueba#

cargo run -p sandboxctl -- markets check --case CM-05

Ejecuta los escenarios de este caso y compara cada uno con lo que declara de antemano que debe salir. Corre en cada commit: si el caso deja de detectar lo que dice detectar, la integración continua se pone roja.

cargo test -p sandbox-markets intermediation

Los invariantes del módulo, incluidos los que ningún escenario de arriba cubre.

Sigue en prototype, no en functional. Los escenarios se ejecutan y pasan, pero el caso no emite evidencia firmada por ejecución ni se ha usado contra datos que no sean los suyos. La regla completa está en el ROADMAP.

Ver también: Catálogo completo · CM-09 · vigilancia · CM-04 · enrutamiento