Saltar al contenido
ALX Quant
← M0.4 · TradingView desde cero

Lección 320 min60 XPGratis

Alertas: que TradingView te avise, y luego que avise a tu bot

Al terminar sabrás

  • Crear alertas de precio, de indicador y de condición compuesta en TradingView
  • Escribir tu primer indicador en Pine Script v6 con una alerta y un mensaje con variables
  • Conectar una alerta a Telegram mediante webhook y entender qué puede fallar por el camino

Antes de esta conviene haber hecho Indicadores: qué calculan de verdad y por qué la mitad son la misma cosa.


Mirar el gráfico ocho horas al día no es una estrategia, es un trabajo mal pagado. Las alertas son el primer paso para separar tu atención de tu sistema: defines una condición, te vas, y el sistema te avisa. Y el segundo paso, que hacemos aquí, es que en vez de avisarte a ti, avise a un programa. Ahí empieza la automatización.

El problema

Las alertas de TradingView son fáciles de crear y fáciles de crear mal. Una alerta que se dispara "cuando el RSI cruza 30" puede dispararse decenas de veces en una barra si la evaluas en cada tick, o dispararse sobre un valor que luego cambia (repintado), o llegar a Telegram 40 segundos tarde. Esta lección te enseña a construirlas para que el aviso signifique exactamente lo que crees.

Tres capas

Intuición

Una alerta es un vigilante al que le dices "si pasa esto, llámame". Lo importante es definir bien "esto" y "cuándo mirar". Si le dices "avísame si el precio está por encima de 5.400", te llamará sin parar mientras lo esté. Si le dices "avísame cuando cruce 5.400 hacia arriba", te llamará una vez por cruce. Y si le dices "mira solo al cierre de cada vela", te llamará una vez como mucho por vela, con un dato ya cerrado que no va a cambiar.

Luego está a quién llama. Al principio a ti, al móvil. Después, a una dirección web (un webhook) donde hay un programa escuchando. Ese programa puede reenviar el aviso a un grupo de Telegram, guardarlo en una base de datos o, más adelante en el curso, mandar una orden. La alerta es el mismo vigilante; solo cambia el número al que llama.

Ejemplo numérico

Tres alertas sobre MES, y cuántas veces se disparan en una sesión típica según cómo las configures:

AlertaCondiciónFrecuencia de evaluaciónDisparos en una sesión (orden de magnitud)
PrecioCierre > 5.400Cada vez que cambia el precioCientos, si el precio ronda el nivel
PrecioCruza 5.400 hacia arribaUna vez por cruce1-5
IndicadorRSI(14) cruza 30 hacia arriba, evaluado al cierre de la barra de 15 minUna vez por barra como máximo0-2

La segunda columna es la que casi todo el mundo deja por defecto. "Una vez por barra al cierre" es la configuración honesta para casi cualquier señal basada en indicadores: la barra está cerrada, el valor ya no cambia y coincide con lo que verías en un backtest.

Latencia de la cadena TradingView → webhook → Telegram: del orden de 1-10 segundos en condiciones normales; hasta minutos si el servidor intermedio está saturado. Para barras de 15 minutos, irrelevante. Para barras de 1 minuto, ya es un 15 % de la barra.

Formal

Tipos de alerta en TradingView. (1) Sobre precio: cruces, entradas y salidas de canal, movimientos porcentuales. (2) Sobre indicador: cualquier plot o condición expuesta por el script. (3) Sobre estrategia (strategy()): órdenes generadas por el backtester de Pine. (4) Sobre dibujos: líneas de tendencia, niveles.

Frecuencia de evaluación (trigger): Once per bar (en la primera activación dentro de una barra), Once per bar close (al cierre), Once per minute, Only once. La única que garantiza coherencia con un backtest de barras es once per bar close: cualquier otra evalúa sobre una barra en formación cuyo cierre aún no existe. Una alerta intrabarra sobre un indicador que usa el cierre está evaluando un valor provisional; cuando la barra cierre, el indicador puede haber cambiado y la señal desaparecer. Eso es repintado, y la mitad de las "estrategias" que se venden en internet lo tienen.

Pine Script v6. Lenguaje de TradingView, ejecutado barra a barra sobre el histórico y luego en tiempo real. Dos primitivas de alerta: alertcondition(cond, title, message) define una condición seleccionable en el diálogo de alertas (el mensaje puede incluir placeholders como {{close}}, {{ticker}}, {{interval}}); alert(message, freq) dispara desde dentro del script con alert.freq_once_per_bar_close como frecuencia recomendada, y permite componer el mensaje con variables del script (str.tostring(...)). Para webhooks conviene que el mensaje sea JSON válido.

Webhook. Al crear la alerta se marca "Webhook URL" y se introduce una URL HTTPS pública; TradingView hace un POST con el mensaje como cuerpo. Restricciones: solo puerto 443 (o 80), sin autenticación en cabeceras (la "clave" hay que meterla en el cuerpo del mensaje y verificarla en el servidor), sin garantía de entrega ni de orden, y desde un conjunto de IPs publicadas por TradingView que conviene filtrar. Del lado del servidor necesitas algo que reciba el POST y lo reenvíe a Telegram vía la API de bots (sendMessage). Opciones: un servicio intermedio sin código, o un pequeño servidor propio (Flask/FastAPI en un VPS barato), que es lo que hacemos en M2.4.

Modelo mental de fiabilidad. La alerta puede no dispararse (TradingView caído, script con error en tiempo real), dispararse tarde (cola del webhook) o dispararse dos veces (reintento). Un bot que actúe sobre alertas necesita idempotencia (ignorar duplicados por id de barra) y un heartbeat que le diga que TradingView sigue vivo. Todo eso está en M5.2; aquí basta con saber que la cadena no es infalible.

Ejemplo trabajado con código

Tu primer indicador en Pine v6: EMA de 20, cruce del precio, y una alerta con mensaje JSON listo para un webhook. Se pega en el editor Pine de TradingView (no se ejecuta en Python).

//@version=6
indicator("ALX · Cruce EMA20 con alerta", overlay = true)
 
longitud = input.int(20, "Longitud EMA", minval = 2)
ema = ta.ema(close, longitud)
plot(ema, "EMA", color = color.new(#4C82FB, 0), linewidth = 2)
 
cruceArriba = ta.crossover(close, ema)     // el cierre pasa de estar por debajo a estar por encima
cruceAbajo  = ta.crossunder(close, ema)
 
plotshape(cruceArriba, "Cruce arriba", shape.triangleup,   location.belowbar, color.new(#2DD4BF, 0), size = size.small)
plotshape(cruceAbajo,  "Cruce abajo",  shape.triangledown, location.abovebar, color.new(#F2705B, 0), size = size.small)
 
// Mensaje JSON con variables del script; se envía SOLO al cierre de la barra (sin repintado)
mensaje(direccion) =>
    '{"origen":"ALX","simbolo":"' + syminfo.ticker + '","tf":"' + timeframe.period +
    '","senal":"' + direccion + '","cierre":' + str.tostring(close, format.mintick) +
    ',"ema":' + str.tostring(ema, "#.##") + ',"hora":"' + str.format_time(time_close, "yyyy-MM-dd HH:mm", "UTC") + '"}'
 
if barstate.isconfirmed and cruceArriba
    alert(mensaje("largo"), alert.freq_once_per_bar_close)
if barstate.isconfirmed and cruceAbajo
    alert(mensaje("corto"), alert.freq_once_per_bar_close)
 
// Condiciones seleccionables en el diálogo de alertas (para alertas manuales sin webhook)
alertcondition(cruceArriba, "Cruce EMA arriba", "{{ticker}} cruza EMA hacia arriba en {{interval}} · cierre {{close}}")
alertcondition(cruceAbajo,  "Cruce EMA abajo",  "{{ticker}} cruza EMA hacia abajo en {{interval}} · cierre {{close}}")

El script compila en el editor Pine v6 de TradingView. Un mensaje típico que llegaría al webhook tendría esta forma (los valores dependen del momento en que se dispare):

{"origen":"ALX","simbolo":"MES1!","tf":"15","senal":"largo","cierre":5401.25,"ema":5399.87,"hora":"2026-09-22 14:15"}

Lo importante del diseño: barstate.isconfirmed y alert.freq_once_per_bar_close juntos garantizan un disparo por barra, sobre datos cerrados. Sin ellos, la alerta se evalúa en formación y repinta.

Figura

Diagrama de flujo horizontal: gráfico de TradingView con el indicador → 'alerta (once per bar close)' → 'POST HTTPS al webhook' → 'tu servidor (verifica clave, ignora duplicados)' → 'API de Telegram sendMessage' → móvil con el mensaje. Debajo de cada flecha, la latencia típica: instantáneo, 1-5 s, <1 s, <1 s. Una bifurcación en coral desde el servidor con la etiqueta 'M2.4: aquí también puede ir una orden al broker'.
Cada flecha puede fallar o llegar tarde. Por eso el servidor verifica, deduplica y registra; y por eso las decisiones importantes esperan al cierre de la barra.

(Figura estática en SVG.)

El error típico

Crear la alerta con la frecuencia por defecto y una condición de indicador. La alerta se dispara en mitad de la barra, con un RSI que aún puede moverse cinco puntos antes del cierre. Ves la señal, entras, y al cerrar la barra el RSI está en 32 y la señal "nunca existió". El backtest de esa misma regla, que solo ve cierres, no tiene ese problema, y por eso el backtest gana y tú no. Repintado no es un bug de TradingView: es evaluar sobre datos que aún pueden cambiar. La solución es siempre la misma: once per bar close y barstate.isconfirmed, aceptando que operas al cierre de la barra y no en el instante mágico en que el indicador tocó el nivel.

Quiz

5 preguntas · se aprueba con 60 %

  1. 1.¿Qué frecuencia de alerta coincide con lo que ve un backtest de barras?

  2. 2.Una alerta sobre RSI se dispara a mitad de barra y al cerrar la barra la condición ya no se cumple. Esto es:

  3. 3.TradingView envía el webhook:

  4. 4.En Pine v6, para que `alert()` dispare una vez por barra sobre datos cerrados:

  5. 5.Un bot recibe la misma alerta dos veces por un reintento del webhook. Debería:

0 de 5 respondidas

Ejercicio

  1. Pega el indicador en el editor Pine, añádelo a MES1! en 15 min y crea una alerta con la condición "Cruce EMA arriba", frecuencia once per bar close, notificación al móvil. Déjala una sesión y anota cuántas veces se dispara.
  2. Crea un bot de Telegram con @BotFather, obtén el token y tu chat_id, y prueba sendMessage desde el navegador con la URL de la API. No conectes todavía el webhook: eso es M2.4, cuando tengas un servidor que verifique y deduplique.

Resultado verificable: la alerta de cruce de EMA20 en 15 min se dispara entre 0 y 4 veces en una sesión regular de MES en un día normal; si se dispara más de 10, revisa la frecuencia (probablemente está en once per bar). El mensaje de prueba de Telegram debe llegar en menos de un segundo.

Qué te llevas

  1. Una alerta es una condición + una frecuencia de evaluación + un destino. La frecuencia honesta es "al cierre de la barra".
  2. Repintado = evaluar sobre datos provisionales. Se evita con barstate.isconfirmed y freq_once_per_bar_close.
  3. El webhook es una llamada HTTP sin garantías. Quien la recibe verifica, deduplica y registra antes de hacer nada.

Siguiente lección: Replay y el simulador de estrategias: ensayar sin dinero y sin engañarte. La función de repetición de TradingView, cómo usarla para practicar decisiones y por qué el backtester de Pine no sustituye a Python.