El catálogo de 386 indicadores¶
Si preguntas al banco de pruebas «¿cuántos indicadores tienes?», la respuesta honesta tiene
varios números: 386 descubiertos; 375 ejecutables por la API: 33 con fórmula canónica y
paridad verificada y 342 por paso directo al motor sin garantías canónicas; 11 no ejecutables
con motivo. Este capítulo explica de dónde salen, cómo se consulta el catálogo y cómo se lee la ficha de un indicador, tanto de uno
registrado por el proyecto (rsi) como de uno que solo existe en su motor (alma).
Qué vas a aprender¶
- Cómo se construye el catálogo por introspección de los dos motores.
- Qué significan 386, 346, 36, 15, 39, 375, 33, 342 y 11.
- Cómo consultar el catálogo con
GET /v1/indicatorsy sus filtros. - Cómo pedir ayuda con
GET /v1/helpyGET /v1/help/{name}. - Cómo leer la tabla
docs/INDICATORS.md. - La diferencia práctica entre una ficha registrada y una solo de motor.
1. De dónde salen los 386¶
flowchart LR
VTA[vector_ta 0.2.8<br/>funciones batch<br/>+ clases *Stream] --> CAT[finazbench/features/catalog.py<br/>introspección + sonda]
NT[nautilus_trader 1.231.0<br/>subclases de Indicator<br/>update_raw / handle_bar] --> CAT
REG[registro del proyecto<br/>39 primitivas] --> CAT
CAT --> API[GET /v1/indicators]
CAT --> MD[docs/INDICATORS.md<br/>tools/list_indicators.py]
El catálogo es la unión de lo que exponen los motores instalados más las primitivas del proyecto,
con los nombres de ambos motores fusionados en una sola entrada cuando son el mismo indicador (por
ejemplo, rsi agrupa vector_ta.rsi, RsiStream y RelativeStrengthIndex de Nautilus).
| Cifra | Qué cuenta |
|---|---|
| 386 | entradas del catálogo (unión de motores + proyecto) |
| 346 | entradas con carril VectorTA (batch y/o stream) |
| 36 | entradas con carril Nautilus (nativo y/o stream) |
| 15 | entradas expuestas por ambos motores |
| 39 | primitivas registradas del proyecto (fórmula canónica, paridad, aprobación) |
| 347 | entradas solo de motor (386 − 39): registered: false, nivel discovered |
| 375 | ejecutables por POST /v1/indicators (medido por tools/probe_indicators.py) |
| 33 | …de ellas, en modo canónico (execution_mode: canonical): primitivas registradas |
| 342 | …de ellas, por paso directo al motor (engine_passthrough): 323 con VectorTA y 21 con Nautilus (2 en ambos) |
| 11 | no ejecutables, con not_computable_reason: 6 primitivas que leen series derivadas o paneles y 5 indicadores de motor |
Las 15 que tienen los dos motores
sma, ema, rma, rsi, bbands, atr, donchian, wma, hma, macd, keltner_sma,
stochrsi, dmi, psychological_line y vertical_horizontal_filter. Que ambos motores tengan
un nombre no implica que calculen lo mismo: ver las variantes en el capítulo de motores.
386 no son 386 cálculos soportados
Leer «386 indicadores» como «386 cálculos con garantías» es un error factual: solo 33 tienen
fórmula canónica y paridad; los 342 de paso directo son «lo que diga el motor». Y leer «39
aprobados» como «aprobados para producción» es uno peor: ninguno lo está (production: false). El
capítulo siguiente explica los niveles.
2. Consultar el catálogo: GET /v1/indicators¶
Arranca la API del banco y apunta a ella:
docker compose --profile bench-api up -d bench-api # Swagger: http://localhost:8000/docs
BASE=http://localhost:8000
# Catálogo completo: count / total / catalog_size
curl -sS "$BASE/v1/indicators" | jq '.payload | {count, total, catalog_size}'
# Solo los que tienen carril en VectorTA y están registrados
curl -sS "$BASE/v1/indicators?engine=vectorta®istered=true" | jq '.payload.count'
# Búsqueda por subcadena en nombre y descripción
curl -sS "$BASE/v1/indicators?q=bollinger" | jq '.payload.indicators[] | {name, both_engines}'
# Las 39 primitivas aprobadas (33 ejecutables en modo canónico)
curl -sS "$BASE/v1/indicators?approved=true" | jq '.payload.count'
# Cuántos calcula la API y por qué modo
curl -sS "$BASE/v1/indicators" | jq '.payload | {computable_via_api, capability_counts}'
curl -sS "$BASE/v1/indicators?mode=passthrough" | jq '.payload.total' # 347 (342 ejecutables)
| Filtro | Valores | Efecto |
|---|---|---|
engine |
all, vectorta, nautilus |
entradas con carril en ese motor |
registered |
all, true, false |
primitivas del proyecto frente a solo-motor |
verified |
booleano | solo las verificadas por tests |
approved |
booleano | solo las aprobadas (benchmark + research) |
mode |
all, canonical, passthrough |
primitivas registradas frente a entradas de paso directo |
q |
texto | subcadena en nombre y descripción |
Cada entrada lleva su bloque capability y el payload trae capability_counts, de modo que un
cliente nunca tiene que adivinar qué es ejecutable. Hay respuestas reales guardadas en
examples/api/ (08_indicators_catalog.response.json, 11_indicators_catalog_nautilus.response.json,
16_indicators_catalog_approved.response.json).
3. Pedir ayuda: GET /v1/help¶
curl -sS "$BASE/v1/help" # índice de temas
curl -sS "$BASE/v1/help/rsi" | jq # indicador registrado
curl -sS "$BASE/v1/help/alma" | jq # indicador solo de motor
curl -sS "$BASE/v1/help/P01" | jq # estrategia (template)
El índice tiene 417 temas = 39 primitivas + 347 indicadores solo de motor + 31 templates de
estrategia (total: 417 en examples/api/12_help_index.response.json).
4. Dos fichas, dos mundos¶
4.1 rsi: una primitiva registrada¶
Extracto de examples/api/13_help_indicator_rsi.response.json:
{
"id": "rsi",
"kind": "indicator",
"summary": "Wilder RSI from the RMA of gains and losses over the first n differences; flat = 50, gains only = 100, losses only = 0.",
"project": {"registered": true, "primitive": "rsi", "phase": "A"},
"inputs": ["close"], "outputs": ["rsi"],
"first_valid_rule": "period",
"params": [{"name": "period", "type": "int", "required": true, "example": 14}],
"capability": {
"level": "approved", "computable_via_api": true,
"evidence": {"feature_fidelity": "tests/features/test_canonical.py::TestRsi",
"parity": "tests/features/test_parity.py"},
"approval": {"scope": ["benchmark", "research"], "production": false}
},
"availability": {
"vectorta": {"batch": {"state": "native", "variant": "canonical"},
"stream": {"state": "native", "variant": "canonical"}},
"nautilus": {"native": {"state": "variant", "variant": "nt_init_period_minus_1_scaled_0_1",
"note": "Seeds at period−1 (canonical: period) and works internally in 0..1; the provider rescales it to 0..100."}}
}
}
Qué te dice la ficha, en castellano:
- Fórmula: RSI de Wilder; plano = 50, solo ganancias = 100, solo pérdidas = 0.
- Contrato: entra
close, salersi, válido desdeperiod(14 con el ejemplo). - Evidencia: el test de fidelidad y el de paridad que respaldan la afirmación.
- Por motor: VectorTA reproduce la canónica en batch y stream; Nautilus es una variante
(arranca en
period − 1y trabaja en 0..1).
Y como está registrada, se puede calcular por la API común:
curl -sS -X POST "$BASE/v1/indicators" -H 'Content-Type: application/json' \
-d @examples/api/05_indicators_rsi14_nvda.request.json | jq '.payload.status'
# "PASS" — con engine "both", compara VectorTA y Nautilus y devuelve la paridad
En la respuesta real (05_indicators_rsi14_nvda.response.json) VectorTA declara
first_valid_index: 14, n_bars_in: 631735, n_valid: 631721 y leading_nan: 14 sobre NVDA
1min, con el data_hash e8b5fc36… en la firma.
4.2 alma: un indicador solo de motor¶
Extracto de examples/api/14_help_engine_only_alma.response.json:
{
"id": "alma",
"kind": "engine_indicator",
"project": {"registered": false, "primitive": null, "phase": null},
"capability": {"level": "discovered", "computable_via_api": true,
"execution_mode": "engine_passthrough", "computable_engines": ["vectorta"],
"guarantees": {"canonical_formula": false, "first_valid_rule": "observed",
"parity": "not_applicable"}},
"engines": {"vectorta": true, "nautilus": false},
"engines_detail": {"vectorta": {
"function": "alma", "batch_function": "alma_batch", "stream_class": "AlmaStream",
"signature": "(data, period, offset, sigma, kernel=None)"}}
}
alma existe en VectorTA pero no tiene contrato del proyecto: ni formula_version, ni
first_valid declarado, ni tests. Aun así, POST /v1/indicators lo calcula por paso directo al
motor (execution_mode: engine_passthrough): devuelve los valores de VectorTA con el
first_valid observado y sin paridad (ejemplo real en examples/api/17_indicators_alma_passthrough.*,
explicado en Indicadores por API). También puedes usarlo
directamente con su motor:
import vector_ta as va
out = va.alma(close, period=9, offset=0.85, sigma=6.0) # batch
stream = va.AlmaStream(period=9, offset=0.85, sigma=6.0) # incremental
valor = stream.update(close_t)
¿Y si quiero alma con garantías canónicas?
El paso directo no lo promueve. Hay que promoverlo: fórmula canónica, parámetros, first_valid, warmup, test de fidelidad,
paridad por carril y registro de aprobación. Es el checklist del capítulo siguiente.
5. La tabla docs/INDICATORS.md¶
Generada por tools/list_indicators.py; una fila por indicador canónico.
| Columna | Significado |
|---|---|
VectorTA batch / VectorTA stream |
el motor expone función completa / clase incremental |
Nautilus native / Nautilus stream |
el motor expone clase de indicador / update_raw/update_bar |
Registered |
true para las 39 primitivas |
Phase |
A, B o C para las registradas; - para el resto |
Params |
nombres de parámetros de ejemplo |
Level |
discovered, implemented, verified o approved |
Muestra real:
| Indicator | VectorTA batch | VectorTA stream | Nautilus native | Nautilus stream | Registered | Phase | Params | Level |
|---|---|---|---|---|---|---|---|---|
| rsi | true | true | true | true | true | A | period | approved |
| tr | false | false | false | false | true | A | approved | |
| macd | true | true | true | true | true | B | fast,slow,signal | approved |
| session_vwap | false | false | false | false | true | B | approved | |
| alma | true | true | false | false | false | - | discovered |
Observa tr: ningún motor lo expone como función suelta y, sin embargo, es una primitiva aprobada.
Es un cálculo propio (custom_reference) con su test. Registrado no significa «nativo de un
motor».
docker compose --profile dev run --rm -T dev python tools/list_indicators.py \
--format md --output docs/INDICATORS.md # también --format csv
Resumen¶
- El catálogo es la unión introspectada de VectorTA 0.2.8, NautilusTrader 1.231.0 y el registro del proyecto: 386 entradas (346 VectorTA, 36 Nautilus, 15 en ambos).
- 386 descubiertos; 375 ejecutables por la API: 33 con fórmula canónica y paridad verificada y 342 por paso directo al motor sin garantías canónicas; 11 no ejecutables con motivo.
- Las 39 primitivas registradas tienen contrato; las 347 solo de motor siguen en
discoveredaunque se calculen por paso directo. GET /v1/indicatorsfiltra porengine,registered,verified,approvedyq;GET /v1/helpindexa 417 temas.- Una ficha registrada trae fórmula, contrato, evidencia y disponibilidad por motor; una solo de motor trae la firma nativa y cómo llamarla.
Para practicar¶
- Con la API levantada, cuenta cuántas entradas devuelve
engine=nautilus®istered=false. ¿Cuadra con 36 − (registradas con carril Nautilus)? - Busca con
q=vwapy explica por quésession_vwapesapprovedperovwapesdiscovered. - Pide
GET /v1/help/macdy anota qué variante declara cada motor. - Intenta calcular
almaconPOST /v1/indicatorsy copia el código de error. ¿Qué dos formas hay de obtener el número?