P06 · Supertrend¶
| Campo | Valor |
|---|---|
| Familia | Tendencia · parada dinámica por volatilidad con bandas recursivas; dirección continua (siempre largo o corto tras el warmup) |
| Features requeridas | supertrend (salidas upper_final, lower_final, direction), que depende de atr{period} (RMA de tr) y de hl2 |
| Parámetros y defaults | period = 10, multiplier = 3.0 |
| Rejilla del catálogo | period ∈ {7, 10, 14, 21}, multiplier ∈ {1.5, 2.0, 2.5, 3.0, 4.0} → 20 candidatos válidos; 1 tr + 1 hl2 + 4 atr compartidas y 20 recursiones propias |
variant_keys |
period, multiplier |
| Restricciones | period entero ≥ 1 y multiplier > 0 (si no, PolicyParamError) |
first_decision_index |
period − 1 = 9 con defaults (20 con period = 21) |
| Activos y timeframes | NVDA y KO en los 7 TF (1min … 1d); AMZN, INTC, MSFT, TSLA en 1d; BME en 1d con reservas; FX solo con OHLC reparado (las filas con high < low rompen el True Range) |
| Paridad en la matriz | PASS en NT_FEATURES, NT_INTENT_REPLAY y NT_ONLINE(vectorta) (12/12 cada una). UNSUPPORTED en NT_ONLINE(native) (12/12): "nautilus_trader 1.231.0 no ofrece un indicador nativo para 'supertrend'". No es una divergencia: no hay variante nativa que ejecutar |
Fuentes: docs/estrategias/P06.md (especificación), catalog/strategy_catalog.json, docs/DATOS_POR_ESTRATEGIA.md, runs/parity/summary.json.
Qué vas a aprender¶
- Cómo una banda de volatilidad (
HL2 ± m·ATR) se convierte en una parada con memoria gracias a una recursión. - Por qué la banda final no es un mínimo acumulado: la cláusula de reinicio por ruptura del cierre previo la deja volver a subir.
- Que el primer largo de P06 es una semilla (
direction = +1por definición), no una señal. - A seguir en el fixture de la especificación dos reversiones de 2 unidades y la caja fill a fill.
- Por qué cambiar
multiplierrecalcula toda la recursión aunque reutilice el ATR.
La idea en una frase¶
Sigue la tendencia con un "trailing stop" que se mueve solo a favor: mientras el cierre no cruce la banda del lado contrario, mantén la dirección; cuando la cruce, invierte.
Intuición de mercado¶
El Supertrend dibuja una banda a m ATR por encima y por debajo del punto medio de la barra. Estando largo solo importa la banda inferior, que actúa como stop: puede subir (se acerca al precio) pero no bajar mientras el precio respete el stop. Si el cierre perfora esa banda, la tendencia se da por rota y el sistema pasa a corto; desde ese momento vigila la banda superior, que solo puede bajar.
Analogía. Un perro atado a una correa que solo se recoge: mientras el paseante (el precio) avanza, la correa se acorta y el perro (la banda) le sigue de cerca; si el paseante retrocede, la correa no se alarga. Cuando el paseante tira en sentido contrario con fuerza suficiente para cruzar al perro, se cambia de dirección y se ata otra correa por el otro lado.
Por qué podría funcionar. Combina momentum (seguir la dirección vigente) con una distancia de salida proporcional a la volatilidad: en mercados agitados el stop se aleja, en mercados tranquilos se ciñe. Evita salir por ruido "normal" para ese régimen.
Cuándo falla.
- Mercados laterales con volatilidad baja: con
multiplierpequeño las bandas se ciñen y cada oscilación genera una reversión de 2 unidades. - Gaps y huecos de sesión: el True Range de la barra tras un hueco usa el cierre anterior al hueco; la RMA lo arrastra
~5·periodbarras, ensancha las bandas y suprime giros legítimos (KO tiene 271 sesiones ausentes). - Costes: cada cambio de dirección mueve 2 unidades, así que paga doble comisión por señal frente a estrategias con estado plano.
Sesgos típicos al evaluarla.
- Contar la semilla como acierto: el primer largo existe siempre, sea el mercado alcista o bajista.
- Sobreajuste del multiplicador: 20 candidatos con 20 recursiones distintas dan mucho margen para elegir "el mejor" por azar.
- Splits y dividendos: con precios sin ajustar, un split 4:1 genera un TR del 75 % del precio; usa
total_return_adjusted.
Las reglas exactas¶
La regla canónica del catálogo: "Bandas básicas HL2±m·ATR(n). Banda superior final=min(básica,final previa), salvo que el cierre previo supere la superior previa, en cuyo caso se reinicia a básica; inferior simétrica con max y ruptura previa. Dirección inicial +1. Cambiar de -1 a +1 si C>superior final; de +1 a -1 si C<inferior final. Objetivo=dirección cuando es válido."
Toda la recursión vive en la feature supertrend; la política solo traduce direction (±1,0) a objetivo (±1).
Situación en el cierre de t |
Objetivo target[t] |
Motivo (reason) |
|---|---|---|
t < period − 1 (ATR aún NaN) |
0 | WARMUP |
t = period − 1 (siembra, direction = +1) |
+1 | ENTRY |
direction[t] = +1 |
+1 | HOLD / REVERSAL |
direction[t] = −1 |
−1 | HOLD / REVERSAL |
direction[t] NaN tardío |
el anterior | HOLD |
barra no operable (is_tradable = False) |
se congela el publicado | NOT_TRADABLE |
Recursión de la feature para t > s = period − 1:
basic_upper[t] = hl2[t] + m·atr[t] basic_lower[t] = hl2[t] - m·atr[t]
upper_final[t] = basic_upper[t] si basic_upper[t] < upper_final[t-1] o C[t-1] > upper_final[t-1]
upper_final[t-1] en otro caso
lower_final[t] = basic_lower[t] si basic_lower[t] > lower_final[t-1] o C[t-1] < lower_final[t-1]
lower_final[t-1] en otro caso
direction[t] = +1 si direction[t-1] = -1 y C[t] > upper_final[t]
-1 si direction[t-1] = +1 y C[t] < lower_final[t]
direction[t-1] en otro caso
- Entrada: en
t = period − 1siempre largo (semilla). - Salida: no hay estado plano; la salida de un largo es la reversión a corto.
- Reversión: la única transición posible tras el warmup; delta de 2 unidades.
- Desigualdades estrictas en los cuatro sitios:
C[t] == upper_final[t]estando corto no invierte. - Filtros: ninguno.
# decisión en el cierre de t, fill en el open de t+1
target_prev = 0
para cada barra t:
actualizar tr, atr, hl2, bandas finales y direction con datos hasta t
si t < period - 1: target = 0 # WARMUP
si no, si direction[t] > 0: target = +1
si no, si direction[t] < 0: target = -1
si no: target = target_prev # NaN tardío
si target != target_prev:
delta = target - target_prev # +1 en la siembra, ±2 al invertir
orden(delta) -> fill a open[t+1]
target_prev = target
Las bandas comparan con t−1; la dirección, con t
La banda final de t usa la básica de t y el cierre de t−1 frente a la final de t−1. El cambio de dirección compara el cierre de t con la banda final de t. Todo se conoce al cierre de t, así que es causal. Usar C[t] en la cláusula de reinicio es la fuga clásica de las implementaciones caseras.
Los indicadores que usa¶
| Feature | Fórmula | first_valid |
|---|---|---|
tr |
TR[0] = H[0] − L[0]; después max(H − L, |H − Cprev|, |L − Cprev|) |
0 |
hl2 |
(H + L)/2 |
0 |
atr{n} |
RMA de Wilder de tr: semilla SMA(TR[0..n−1]) en n−1; después atr[t] = atr[t−1] + (TR[t] − atr[t−1])/n |
n − 1 |
supertrend{n,m} |
bandas básicas hl2 ± m·atr, recursión de bandas finales y dirección (arriba); siembra direction[n−1] = +1 |
n − 1 (regla chained, no añade barras) |
first_decision_index = period − 1: 9 con defaults, 20 con period = 21. Que TR[0] no sea NaN es lo que hace que el ATR valga ya en n − 1 y no en n.
En el proveedor VectorTA la recursión es NumPy propio sobre vector_ta.atr (variant = "custom_reference_on_vta_atr"): vector_ta.supertrend existe, pero usa otra semilla y devuelve una bandera 0/1, así que no se usa. Su tiempo no debe atribuirse a VectorTA. Más detalle en Las 23 primitivas de fase B, Indicadores paso a paso e Indicadores y features.
Ejemplo barra a barra¶
Fixture §6 de docs/estrategias/P06.md: period = 3, multiplier = 1.0 (fuera de rejilla a propósito, para seguir la recursión a mano), cash_inicial = 1.000,00, tick 0,01, sin costes. first_valid(atr{3}) = first_valid(supertrend) = 2 → first_decision_index = 2.
Las barras 0–1 son WARMUP (ATR NaN): t=0 O=99,50 H=101,00 L=99,00 C=100,00; t=1 O=100,50 H=102,00 L=100,00 C=101,00; ambas con TR = 2,000000, objetivo 0, sin órdenes.
| t | O | H | L | C | ATR(3) | upper_final | lower_final | dir. | target | orden | fill | pos. | PnL acum. sin costes | equity con 5 bps* |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2 | 101,50 | 103,00 | 101,00 | 102,00 | 2,000000 | 104,000000 | 100,000000 | +1 | +1 ENTRY (siembra) | BUY 1 | — | 0 | 0,00 | 1.000,00 |
| 3 | 102,50 | 104,00 | 102,00 | 103,00 | 2,000000 | 104,000000 | 101,000000 | +1 | +1 HOLD | — | 102,50 | +1 | 0,50 | 1.000,45 |
| 4 | 103,50 | 105,00 | 102,00 | 103,00 | 2,333333 | 104,000000 | 101,166667 | +1 | +1 HOLD | — | — | +1 | 0,50 | 1.000,45 |
| 5 | 102,50 | 103,00 | 100,00 | 101,00 | 2,555556 | 104,000000 | 101,166667 | −1 | −1 REVERSAL | SELL 2 | — | +1 | −1,50 | 998,45 |
| 6 | 100,50 | 101,00 | 98,00 | 99,00 | 2,703704 | 102,203704 | 96,796296 | −1 | −1 HOLD | — | 100,50 | −1 | −0,50 | 999,35 |
| 7 | 98,50 | 99,00 | 96,00 | 97,00 | 2,802469 | 100,302469 | 96,796296 | −1 | −1 HOLD | — | — | −1 | 1,50 | 1.001,35 |
| 8 | 96,50 | 97,00 | 94,00 | 95,00 | 2,868313 | 98,368313 | 96,796296 | −1 | −1 HOLD | — | — | −1 | 3,50 | 1.003,35 |
| 9 | 94,50 | 96,00 | 93,00 | 95,00 | 2,912209 | 97,412209 | 91,587791 | −1 | −1 HOLD | — | — | −1 | 3,50 | 1.003,35 |
| 10 | 95,50 | 98,00 | 95,00 | 97,00 | 2,941472 | 97,412209 | 93,558528 | −1 | −1 HOLD | — | — | −1 | 1,50 | 1.001,35 |
| 11 | 97,50 | 100,00 | 97,00 | 99,00 | 2,960982 | 97,412209 | 95,539018 | +1 | +1 REVERSAL | BUY 2 | — | −1 | −0,50 | 999,35 |
| 12 | 99,50 | 102,00 | 99,00 | 101,00 | 2,973988 | 103,473988 | 97,526012 | +1 | +1 HOLD | — | 99,50 | +1 | 0,50 | 1.000,25 |
| 13 | 101,50 | 104,00 | 101,00 | 103,00 | 2,982658 | 103,473988 | 99,517342 | +1 | +1 HOLD | — | — | +1 | 2,50 | 1.002,25 |
| 14 | 103,50 | 105,00 | 102,00 | 104,00 | 2,988439 | 103,473988 | 100,511561 | +1 | +1 HOLD | — | — | +1 | 3,50 | 1.003,25 |
| 15 | 104,50 | 106,00 | 103,00 | 105,00 | 2,992293 | 107,492293 | 101,507707 | +1 | +1 HOLD | — | — | +1 | 4,50 | 1.004,25 |
OHLC, ATR, bandas finales, dirección, objetivos, fills y equity (PnL = equity − 1.000,00) son literales del fixture §6 de docs/estrategias/P06.md; la columna "pos." indica la posición tras el fill en la apertura de esa barra. *"Equity con 5 bps" es cálculo de este manual: escenario hypothetical_5bps (fee_rate = 0,0005, sin spread ni deslizamiento), comisión por fill = |delta| · precio · 0,0005 redondeada al céntimo half-even y restada de la caja en la barra del fill:
- fill 1 (t=3):
1 · 102,50 · 0,0005 = 0,05125 → 0,05 - fill 2 (t=6):
2 · 100,50 · 0,0005 = 0,1005 → 0,10 - fill 3 (t=12):
2 · 99,50 · 0,0005 = 0,0995 → 0,10
Comisiones acumuladas: 0,05 → 0,15 → 0,25. Equity final con 5 bps: 1.004,50 − 0,25 = 1.004,25.
Lo que hay que ver en la tabla:
- Barra 2: primera barra válida y primera entrada a la vez. No es una señal: es la semilla "Dirección inicial +1".
- Barras 3–5:
upper_finalse queda clavada en 104,000000 mientras la básica sube a 105,000000 y 105,833333 (regla delmin). - Barra 5: el largo se corta contra
lower_final = 101,166667, conservada de la barra 4; la básica de la barra 5 estaba mucho más abajo (98,944444). Con una banda "rolling" independiente el corte no habría ocurrido. - Barra 11:
99,00 > 97,412209→ reversión a largo, fill de 2 unidades en el open de 12 (99,50). - Barras 12 y 15: reinicio de
upper_finalpor ruptura del cierre previo (C[11] = 99,00 > 97,412209;C[14] = 104,00 > 103,473988). La posición larga queda abierta al final y se valora al último cierre.
Las cuentas de las barras clave¶
Siembra (t=2): TR[0] = 101-99 = 2; TR[1] = max(2, 2, 0) = 2; TR[2] = max(2, 2, 0) = 2
ATR[2] = (2+2+2)/3 = 2,000000; HL2[2] = (103+101)/2 = 102,000000
upper_final[2] = 102 + 1·2 = 104,000000; lower_final[2] = 100,000000
direction[2] = +1 -> target +1 (ENTRY)
Reversión (t=5): TR[4] = max(3, 2, 1) = 3; TR[5] = max(3, 0, 3) = 3
ATR[4] = (1/3)·3 + (2/3)·2 = 7/3 = 2,333333
ATR[5] = (1/3)·3 + (2/3)·(7/3) = 23/9 = 2,555556
basic_lower[5] = 101,50 - 2,555556 = 98,944444
¿98,944444 > lower_final[4]=101,166667? No. ¿C[4]=103 < 101,166667? No.
-> lower_final[5] = 101,166667 (se conserva)
C[5] = 101,00 < 101,166667 -> direction -1 (REVERSAL, delta -2)
Reversión (t=11): C[11] = 99,00 > upper_final[11] = 97,412209 -> direction +1 (delta +2)
Reinicio (t=15): C[14] = 104,00 > upper_final[14] = 103,473988 -> upper_final[15] = básica = 107,492293
Caja: 1.000,00 - 102,50 = 897,50 (fill 1, open[3])
897,50 + 2·100,50 = 1.098,50 (fill 2, open[6])
1.098,50 - 2·99,50 = 899,50 (fill 3, open[12])
Equity final: 899,50 + 1·105,00 = 1.004,50
Sin la cláusula de reinicio, upper_final[15] se habría quedado en 103,473988, por debajo del cierre: el test test_p06_band_reset_on_previous_close_break de la especificación compara exactamente esa variante mutilada.
Diagrama¶
flowchart LR
W(["WARMUP: t < period-1"]) -->|"t = period-1 · siembra · BUY 1"| L["Largo +1"]
L -->|"C < lower_final · SELL 2"| S["Corto -1"]
S -->|"C > upper_final · BUY 2"| L
L -->|"C >= lower_final"| L
S -->|"C <= upper_final"| S
No existe estado plano tras el warmup: el primer paso es siempre a largo y después solo hay reversiones de 2 unidades.
Cómo lanzarla¶
Backtest con ambos motores sobre NVDA 1d con los defaults (la estrategia se pasa por plantilla y parámetros, forma "inline" de la API de backtesting):
BASE=http://localhost:8000
SID=$(curl -sS -X POST "$BASE/v1/backtest" -H 'Content-Type: application/json' -d '{
"request_id": "manual-p06-0001",
"correlation_id": null,
"schema_version": "v1",
"payload": {
"strategy": {"template_id": "P06", "params": {"period": 10, "multiplier": 3.0},
"name": "Supertrend 10/3.0 base", "register": true},
"data": {"asset_id": "NVDA", "timeframe": "1d",
"window": {"start": "2015-01-01T00:00:00Z", "end": "2025-01-01T00:00:00Z",
"mode": "reset_flat"}},
"execution": {"lane": "SIM-S", "contract_version": "1", "initial_cash": 100000,
"target_lots": [-1, 0, 1], "cost_scenario": "hypothetical_5bps"},
"engine": "both",
"cache": {"cache_mode": "WARM_FEATURES", "write_through": true},
"output": {"output_mode": "metrics", "include_timings": true,
"include_parity": true, "tail_rows": 5},
"engine_options": {"vectorta": {"kernel": "scalar", "use_batch": true},
"nautilus": {"adapter": "NT_FEATURES"}}
}}' | jq -r '.payload.signature.strategy_id')
echo "$SID"
import uuid, requests
BASE = "http://localhost:8000"
env = lambda payload: {"request_id": str(uuid.uuid4()), "correlation_id": None,
"schema_version": "v1", "payload": payload}
payload = {
"strategy": {"template_id": "P06", "params": {"period": 10, "multiplier": 3.0},
"register": True},
"data": {"asset_id": "NVDA", "timeframe": "1d",
"window": {"start": "2015-01-01T00:00:00Z",
"end": "2025-01-01T00:00:00Z", "mode": "reset_flat"}},
"execution": {"lane": "SIM-S", "contract_version": "1", "initial_cash": 100000,
"target_lots": [-1, 0, 1], "cost_scenario": "hypothetical_5bps"},
"engine": "both",
"output": {"output_mode": "metrics", "include_parity": True},
"engine_options": {"vectorta": {"kernel": "scalar", "use_batch": True},
"nautilus": {"adapter": "NT_FEATURES"}},
}
r = requests.post(f"{BASE}/v1/backtest", json=env(payload)).json()["payload"]
SID = r["signature"]["strategy_id"]
print(SID, r["parity"]["verdict"])
No pidas indicator_provider: "native" en Nautilus: para P06 es UNSUPPORTED por motivo terminal (Nautilus no tiene supertrend, tr ni hl2).
Derivar una variante con un multiplicador más ceñido:
curl -sS -X POST "$BASE/v1/strategies/$SID/derive" -H 'Content-Type: application/json' -d '{
"request_id": "manual-p06-derive", "correlation_id": null, "schema_version": "v1",
"payload": {"param_overrides": {"multiplier": 2.0}, "name": "Supertrend 10/2.0",
"slug": "supertrend-10-2-0", "tags": ["sensibilidad"]}}' | jq '.payload.strategy_id, .payload.cache_forecast'
multiplier es parámetro de feature. Según la tabla de invalidación §5.3 de la especificación, cache_forecast debe anunciar aciertos en tr, hl2 y atr{10} y un fallo en supertrend{10, 2.0}: la recursión entera se recalcula porque min(básica, final previa) no se distribuye sobre el multiplicador. Cambiar period (10 → 14) falla además en atr{14}.
Sweep de sus variant_keys (rejilla completa del catálogo):
curl -sS -X POST "$BASE/v1/sweep" -H 'Content-Type: application/json' -d '{
"request_id": "manual-p06-sweep", "correlation_id": null, "schema_version": "v1",
"payload": {"base_strategy_id": "'"$SID"'",
"grid": {"period": [7, 10, 14, 21], "multiplier": [1.5, 2.0, 2.5, 3.0, 4.0]},
"candidate_policy": {"drop_invalid": true, "drop_duplicates": true,
"register_strategies": true,
"name_template": "{template_name} {period}/{multiplier}"},
"data": {"asset_id": "NVDA", "timeframe": "1d",
"window": {"start": "2015-01-01T00:00:00Z", "end": "2025-01-01T00:00:00Z", "mode": "reset_flat"}},
"execution": {"lane": "SIM-S", "contract_version": "1", "initial_cash": 100000,
"cost_scenario": "hypothetical_5bps"},
"engine": "vectorta", "cache": {"cache_mode": "OPT_FULL"},
"output": {"output_mode": "metrics"},
"engine_options": {"vectorta": {"kernel": "scalar", "use_batch": true}}}}' | jq '.payload.job_id, .payload.factorization_plan'
Según §5.4 de la especificación: 20 candidatos, los 20 válidos. El resultado se consulta en GET /v1/jobs/{job_id}.
Cuánto cuesta la rejilla¶
| Concepto | Cuenta |
|---|---|
| Candidatos cartesianos | 4 period × 5 multiplier = 20 |
| Inválidos | 0 (todos cumplen period ≥ 1 y multiplier > 0) |
| Curvas compartidas | tr (1) + hl2 (1) + atr{7,10,14,21} (4) = 6 |
| Recursiones propias | 20, una por pareja, 3 salidas cada una; no se comparten |
| Pasadas sin factorizar / con factorizar | 80 / 26 (ahorro de 54 pasadas, 67,5 %) |
Es el caso peor de invalidación del grupo: a diferencia de P04, donde cambiar k recombina curvas ya calculadas, aquí cada multiplier alimenta una recursión acoplada distinta. El bucle de la recursión es el coste dominante y el candidato natural a Numba. Un cambio de fee_rate o de initial_cash no toca features: solo rehace el ledger.
Qué mirar en los resultados¶
parity.verdicten los carriles soportados; conNT_ONLINEusa la ruta por defecto (stream propio sobreAtrStream), no la nativa.- Número de cambios de dirección: en P06 es igual al número de fills tras el primero, y la suma de
|delta_q|= 2 × (fills − 1) + 1. Es un invariante comprobable. - Duración media de cada tramo direccional y fracción de barras en +1 frente a −1.
- Diagnóstico de banda: fracción de barras con
ATR == 0(típico en1min) y ATR media relativa al precio (atr/close); explican un número anómalo de giros en intradía. - Fracción de reinicios por ruptura del cierre previo: es lo que distingue esta implementación de una "rolling monótona".
- Costes: pesan el doble por señal que en P02 o P11; dilo al comparar estrategias con 5 bps.
- Aviso
DATA_GAP_SESSIONSen KO: la cadena recursiva arrastra el TR del hueco; el resultado debe publicarse con la advertencia. - Paridad por salida: la primera divergencia se reporta por separado en
upper_final,lower_finalydirection, para distinguir "difiere el ATR" de "difiere la recursión".
Causalidad comprobada¶
El test de "futuros alterados" de la especificación (test_p06_future_perturbation): sobre NVDA 1d (600 barras, 10/3.0) se ensancha el rango de cada barra posterior a la 400 (high += 4, low −= 4, sin tocar el cierre), de modo que la perturbación entra solo por el True Range. Todo lo calculado hasta la barra 400 (TR, ATR, HL2, las tres salidas de supertrend, objetivos, motivos, fills con fill_index ≤ 400, caja y equity) debe quedar idéntico bit a bit. Es el test más exigente del grupo: una sola contaminación del ATR se propagaría a toda la recursión posterior, y la variante "hacia atrás" con np.minimum.accumulate lo suspende de inmediato.
Para reanudar en modo continue, el checkpoint necesita cinco escalares de feature: atr[t0−1], close[t0−1], upper_final[t0−1], lower_final[t0−1] y direction[t0−1]. Sin las bandas y la dirección no hay extensión incremental: es un replay completo.
Errores típicos¶
| Error | Consecuencia | Cómo evitarlo |
|---|---|---|
multiplier <= 0 |
PolicyParamError: las bandas colapsan en HL2 y el indicador se vuelve ruido |
La API lo rechaza; en un sweep cuenta como inválido y no desaparece del denominador |
Usar C[t] en la cláusula de reinicio |
Otra señal, no reproducible entre motores | La cláusula compara C[t−1] con upper_final[t−1] |
Calcular la banda con np.minimum.accumulate |
Banda monótona que nunca vuelve a subir (falla en la barra 15 del fixture) | La recursión es un bucle con reinicio; no es un rolling |
| Contar el primer largo como señal | Sesgo en tasas de acierto | Es la semilla direction = +1; exclúyelo del análisis |
| Reutilizar un stream incremental entre candidatos | El segundo candidato hereda bandas del primero, con números plausibles | Los adaptadores construyen streams nuevos por candidato (D-11) |
| Usar precios sin ajustar por splits | TR gigantes y falsos que suprimen giros durante ~5·period barras |
price_basis = total_return_adjusted |
| Usar el Supertrend de VectorTA "porque existe" | Otra semilla y bandera 0/1: otra estrategia | La receta usa custom_reference_on_vta_atr |
Variantes y extensiones¶
- Solo largos:
target_lots = [0, 1]y−1 → 0; habitual en acciones. - Supertrend con ATR de otra media (SMA o EMA del TR): exige su propia entrada de catálogo y otra
formula_version. - Pariente directo: P07 UT Bot, otra parada ATR recursiva, pero con estado plano inicial y cruce del cierre sobre el stop.
- Chandelier: P19 ancla la parada al máximo o mínimo de una ventana en vez de a
HL2. - Parabolic SAR: P14, parada que acelera con el tiempo.
- Filtro de régimen: combinarla con ADX (P15) para evitar los mercados laterales.
Resumen¶
- P06 sigue una dirección continua (+1/−1) que solo cambia cuando el cierre cruza la banda final del lado contrario.
- Las bandas finales son recursivas: se mueven solo a favor, salvo el reinicio cuando el cierre previo rompe la banda previa.
- La primera entrada es la semilla
direction = +1, no una señal; después cada cambio es una reversión de 2 unidades. - En el fixture: largo a 102,50, reversión a corto a 100,50, reversión a largo a 99,50; equity final 1.004,50 (1.004,25 con 5 bps, cálculo propio).
- Paridad PASS en los carriles soportados; la variante nativa de Nautilus es UNSUPPORTED porque no existe el indicador.
Para practicar¶
- Con el fixture, calcula a mano
ATR[6],basic_upper[6]yupper_final[6]a partir deATR[5] = 23/9y comprueba 2,703704 y 102,203704. ¿Qué condición (minUobrkU) hace que la banda cambie? - Rehaz la columna "equity con 5 bps" con 10 bps. ¿Cuánto suman las comisiones? (Pista: 0,10 + 0,20 + 0,20.)
- Lanza el sweep 4×5 sobre NVDA 1d y KO 1d. Compara el número de fills entre
multiplier = 1.5y4.0conperiod = 10, y comprueba el invarianteΣ|delta_q| = 2·(fills − 1) + 1.