Indicadores y features¶
Qué vas a aprender¶
- Qué es un indicador técnico y qué es una feature en este proyecto.
- Por qué un indicador debe ser una función causal.
- Qué son el warmup (calentamiento) y
first_valid, con un ejemplo numérico calculado a mano. - Qué son las variantes entre motores y por qué no son errores.
Este capítulo es conceptual
El catálogo completo (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), los niveles de capacidad y más ejemplos numéricos están en la Parte IV · Indicadores.
De la barra al indicador¶
Un indicador transforma una serie de precios en otra serie que resume algo: la
tendencia (medias móviles), el impulso (RSI), la volatilidad (ATR, Bollinger)… En el
banco, a la serie calculada y lista para que la use una política se le llama
feature. Una feature lleva, además de sus valores, metadatos: su especificación
(FeatureSpec: indicador + parámetros + fuente), su first_valid_index y su máscara
de validez.
flowchart LR
P["close[0..T]"] --> I["Indicador<br/>EMA(periodo=3)"]
I --> F["Feature<br/>valores + first_valid + máscara"]
F --> POL["Política"]
Causalidad: solo el pasado¶
Una función es causal si el valor en la barra t depende únicamente de datos
disponibles hasta t (inclusive). Una media móvil centrada, que usa barras
futuras, no es causal: en un backtest daría señales que nadie podía conocer.
La forma más barata de engañarse
Un indicador no causal hace que cualquier estrategia parezca genial. Por eso el banco compara motores barra a barra: si uno de ellos «mirara el futuro», la paridad lo delataría.
Warmup y first_valid¶
Una media de 3 barras no puede calcularse con 2 barras. Las primeras posiciones de
toda feature son no válidas: el periodo de calentamiento (warmup). El
índice de la primera posición válida es first_valid_index.
Figura 1. Cada indicador necesita un número distinto de barras antes de dar su primer valor válido (índices 0-based).
EMA de periodo 3 con semilla SMA, a mano
Serie de entrada: [1, 2, 3, 4, 5, 6]. Factor de suavizado
α = 2 / (3 + 1) = 0,5.
| t | close | Cálculo | EMA |
|---|---|---|---|
| 0 | 1 | faltan datos | null |
| 1 | 2 | faltan datos | null |
| 2 | 3 | semilla = SMA(1,2,3) = 2 | 2 |
| 3 | 4 | 0,5·4 + 0,5·2 | 3 |
| 4 | 5 | 0,5·5 + 0,5·3 | 4 |
| 5 | 6 | 0,5·6 + 0,5·4 | 5 |
Resultado: [null, null, 2, 3, 4, 5], con first_valid_index = 2.
Este es exactamente el golden del vertical G1 de la plataforma
(ema_period3_golden.json, oráculo migration/baseline/oracle/ema_oracle.py).
Tres reglas que el banco aplica a rajatabla:
- Antes de
first_validno hay valor: esnull/NaN, nunca cero. Un cero fabricaría una señal. - La política no decide antes de tener todas sus features:
first_decision_indexes el máximo de losfirst_valid_indexde todas las features que necesita. Antes, el objetivo es 0 con motivoREASON_WARMUP(que no es lo mismo que decidir estar plano). - La ventana pedida debe cubrir el warmup: si no, la API responde
409 INSUFFICIENT_HISTORYen vez de inventar.
Warmup en un backtest real
En el backtest de P01 (cruce de EMAs 20/50) sobre NVDA diario 2024, la API devuelve
warmup_bars: 49 y first_decision_index: 49: la EMA de 50 no es válida hasta la
barra 49 (ver Tutorial).
Semillas y variantes¶
Dos implementaciones «de la misma EMA» pueden diferir en cómo arrancan: semilla
SMA frente a primer valor, o empezar en period frente a period-1. No es un bug: es
una definición distinta. El banco la llama VARIANT, la declara con un nombre
y la mide.
RSI(14) sobre NVDA diario, ene–feb 2024 (respuesta real de la API)
| Campo | VectorTA | Nautilus |
|---|---|---|
provider.variant |
canonical |
nt_init_period_minus_1_scaled_0_1 |
first_valid_index |
14 | 13 |
| Último valor (2024-02-29) | 72,92 | 70,68 |
La diferencia viene del calentamiento. Por eso la paridad compara desde la primera
barra común y solo exige exactitud en señales, fills y equity; las features
admiten tolerancias registradas con motivo en finazbench/features/compare.py.
Batch frente a stream¶
Un indicador puede calcularse de dos formas:
| Modo | Cómo | Para qué |
|---|---|---|
| batch | Se le da la serie entera y devuelve la serie entera | Backtests rápidos, barridos |
| stream (incremental) | Se le da una observación cada vez y devuelve el valor nuevo | Simular el tiempo real, carril online |
Ambos deben dar el mismo número barra a barra. Comprobarlo es parte de la paridad
(carril NT_ONLINE, ver Carriles).
Resumen¶
- Una feature es un indicador calculado con metadatos: especificación,
first_validy máscara. - Todo indicador debe ser causal; antes de
first_validno hay valor, y nunca se rellena con cero. - EMA(3) con semilla SMA sobre
[1..6]da[null, null, 2, 3, 4, 5]. - Las diferencias de semilla entre motores son
VARIANTdeclaradas, no errores.
Para practicar¶
- Calcula a mano la EMA(2) con semilla SMA de
[2, 4, 6, 8]. - Una política usa EMA(20) y EMA(50). ¿Cuál es su
first_decision_index? - ¿Por qué rellenar el warmup con ceros puede generar una operación falsa en la primera barra?