# Alertas de TradingView a MT5, sin EA ni VPS

URL: https://docs.fxapis.com/es/guides/tradingview

> Convierte alertas de TradingView en órdenes de MetaTrader 5 con una URL de webhook secreta: crea un hook en la consola o con la API, configura la alerta de…



TradingView puede enviar una alerta a una URL, pero no puede agregar un encabezado
`Authorization`, así que no puede llamar a una API normal. La respuesta habitual es un
Expert Advisor en un VPS con Windows, o un puente de pago. fxapis te da en su lugar una
**URL de alerta secreta**: pégala en una alerta de TradingView, y las alertas que se
disparan se convierten en órdenes en tu cuenta de MT5. Nosotros ejecutamos la terminal;
nada tuyo tiene que quedarse encendido.

```
TradingView alert fires
   → POST https://api.fxapis.com/hooks/tradingview/<secret>     answered at once (202)
   → fxapis places the order on your MT5 account(s)             the same path as POST /v1/…/orders/market
   → the alert and its result appear under TradingView in the console
```

Es decir: la alerta se dispara, TradingView hace un `POST` a la URL secreta y recibe
`202` de inmediato; fxapis envía la orden a tu cuenta (o cuentas) de MT5 por el mismo
camino que `POST /v1/…/orders/market`; y la alerta y su resultado aparecen en
TradingView, en la consola.

<Callout type="warn" title="Prueba con una cuenta demo">
  Un hook de alertas envía órdenes reales a la cuenta a la que apunta. Apunta tu primer hook a una
  **cuenta demo de un broker** y dispara una alerta de prueba antes de usar una cuenta con dinero real.
</Callout>

## Lo que necesitas [#what-you-need]

* Un workspace de fxapis con una cuenta de MT5 conectada ([Conecta cuentas de MT5](/es/accounts)).
  Para alertas que deben actuar en menos de un segundo, configura la cuenta como **siempre conectada**:
  una cuenta que se pone en línea a demanda primero tiene que conectarse, lo que tarda unos 10
  segundos según nuestra medición.
* Un plan de TradingView que incluya **alertas por webhook** —la
  [página de precios](https://www.tradingview.com/pricing/) de TradingView lista las notificaciones por
  webhook en sus planes de pago, no en Basic— y la **verificación en dos pasos** activada en tu cuenta
  de TradingView: TradingView solo envía webhooks desde cuentas con 2FA
  ([About webhooks](https://www.tradingview.com/support/solutions/43000529348-about-webhooks/)).
  Ambas cosas revisadas el 30 de septiembre de 2026.

## 1. Crea un hook [#1-create-a-hook]

### En la consola [#in-the-console]

Abre **Console → TradingView → Create a TradingView hook**, y luego:

1. Ponle de **nombre** (Name) la estrategia o el gráfico al que sirve.
2. Elige la **cuenta**. Con varias cuentas, cada alerta envía una
   [orden multicuenta](/guides/multi-account-orders); esto necesita un plan con órdenes multicuenta.
3. Define el **volumen predeterminado** en lotes. Las alertas que no envían volumen lo usan.
4. Indica cómo nombra tu broker los símbolos: un **mapa de símbolos** (`XAUUSD=XAUUSD.a`, uno por línea)
   y/o un **sufijo** agregado a todos los demás símbolos (`.a`, `m`, `.pro`…).
5. Deja **Only from TradingView** activado, a menos que tú mismo envíes alertas de prueba.

La consola muestra entonces la **URL, una sola vez**, con mensajes listos para pegar. Cópiala ahora:
solo guardamos un hash, así que no puede volver a mostrarse. Si la pierdes, **rota** el hook para
obtener una nueva.

Crear y cambiar hooks requiere un **owner o admin** del workspace: la URL de un hook puede abrir
posiciones, así que exige el mismo nivel que crear una clave de trading.

### Con la API [#with-the-api]

Con una clave que tenga `trading:execute`:

```bash
curl -sS -X POST "https://api.fxapis.com/v1/alert-hooks" \
  -H "Authorization: Bearer $FXAPIS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Gold breakout",
    "accountIds": ["2b0c7c1e-5d0b-4d8e-9a53-0e6f3b1c9a10"],
    "defaults": {
      "volume": "0.10",
      "deviationPoints": 30,
      "symbolMap": { "XAUUSD": "XAUUSD.a" },
      "symbolSuffix": "",
      "stripExchangePrefix": true,
      "allowClose": true,
      "onlyTradingViewIps": true
    }
  }'
```

```json
{
  "data": {
    "id": "8f1d…",
    "name": "Gold breakout",
    "url": "https://api.fxapis.com/hooks/tradingview/3q2-7ZkT0d8m1sQe9yVbW4nX6pLr5aHcUgJf0oKxQx4w",
    "urlHint": "https://api.fxapis.com/hooks/tradingview/…Qx4w",
    "enabled": true,
    "…": "…"
  }
}
```

`url` aparece en esta respuesta y en `POST /v1/alert-hooks/{id}/rotate`, y en ningún otro lugar.
Todos los demás endpoints muestran `urlHint`.

| Endpoint                              | Qué hace                                                                        | Alcance           |
| ------------------------------------- | ------------------------------------------------------------------------------- | ----------------- |
| `GET /v1/alert-hooks`                 | Lista los hooks                                                                 | `trading:read`    |
| `POST /v1/alert-hooks`                | Crea uno; devuelve `url` una vez                                                | `trading:execute` |
| `GET /v1/alert-hooks/{id}`            | Lee uno                                                                         | `trading:read`    |
| `PATCH /v1/alert-hooks/{id}`          | Cambia el nombre, las cuentas o los valores predeterminados; la URL se conserva | `trading:execute` |
| `POST /v1/alert-hooks/{id}/rotate`    | URL nueva, devuelta una vez; la anterior deja de funcionar de inmediato         | `trading:execute` |
| `POST /v1/alert-hooks/{id}/disable`   | Pausa: las alertas se rechazan y se registran                                   | `trading:reduce`  |
| `POST /v1/alert-hooks/{id}/enable`    | Reanuda                                                                         | `trading:execute` |
| `DELETE /v1/alert-hooks/{id}`         | Elimina; la URL deja de funcionar para siempre                                  | `trading:execute` |
| `GET /v1/alert-hooks/{id}/deliveries` | Cada alerta recibida y qué pasó con ella                                        | `trading:read`    |

## 2. Configura la alerta en TradingView [#2-set-up-the-alert-in-tradingview]

<Steps>
  <Step>
    ### Abre el diálogo de alertas [#open-the-alert-dialog]

    En el gráfico, abre **Create alert** (el ícono del despertador, o <kbd>Alt</kbd>+<kbd>A</kbd>). Para
    una estrategia, elige la estrategia como **Condition**; para un indicador o un dibujo, elígelo junto
    con el cruce o el nivel que quieras.
  </Step>

  <Step>
    ### Escribe el mensaje [#write-the-message]

    En **Message**, pega uno de los mensajes de abajo. TradingView reemplaza los placeholders `{{…}}`
    cuando se dispara la alerta.
  </Step>

  <Step>
    ### Pega la URL [#paste-the-url]

    En **Notifications**, marca **Webhook URL** y pega la URL del hook.
  </Step>

  <Step>
    ### Créala y revisa el log [#create-it-and-check-the-log]

    Guarda la alerta. Cuando se dispare, aparecerá en **Console → TradingView → tu hook** en menos de un
    segundo, con su resultado. El log de alertas de TradingView también tiene una columna con el estado
    del webhook.
  </Step>
</Steps>

## 3. Mensajes [#3-messages]

Hay mensajes de alerta listos para pegar, para indicadores y estrategias, en JSON o texto plano, en
[fxapis-integrations](https://github.com/FXapis/fxapis-integrations/tree/main/tradingview), junto con
un flujo de n8n que convierte un webhook de TradingView en una orden;
[la guía paso a paso](https://fxapis.com/blog/mt5-api-postman-tradingview-n8n) (en inglés) cubre ambos.

Un mensaje puede ser JSON o una línea de texto; TradingView envía JSON como `application/json` y todo
lo demás como `text/plain`, y fxapis lee ambos.

### Indicadores y dibujos [#indicators-and-drawings]

Una alerta de indicador no sabe nada de posiciones, así que envía una acción fija. Crea una alerta por
dirección:

```json title="Buy"
{ "action": "buy", "symbol": "{{ticker}}", "id": "{{ticker}}-{{timenow}}" }
```

```json title="Sell"
{ "action": "sell", "symbol": "{{ticker}}", "id": "{{ticker}}-{{timenow}}" }
```

Agrega niveles o un volumen si la alerta los conoce:

```json
{ "action": "buy", "symbol": "{{ticker}}", "volume": "0.20", "sl": "2310.5", "tp": "2385", "id": "{{ticker}}-{{timenow}}" }
```

### Estrategias [#strategies]

Una sola alerta cubre cada entrada, salida y reversión de una estrategia:

```json title="Strategy"
{
  "action": "{{strategy.order.action}}",
  "symbol": "{{ticker}}",
  "position": "{{strategy.market_position}}",
  "prev_position": "{{strategy.prev_market_position}}",
  "id": "{{strategy.order.id}}-{{timenow}}"
}
```

`{{strategy.order.action}}` por sí solo no puede distinguir una salida de una entrada: cerrar un long
es un `sell`. Por eso, cuando `position` está presente, decide la posición **después** de la orden:

| `position` después de la orden | `prev_position`         | Qué hace fxapis                                             |
| ------------------------------ | ----------------------- | ----------------------------------------------------------- |
| `flat`                         | cualquiera              | Cierra todas las posiciones abiertas del símbolo            |
| `short`                        | `long` (una reversión)  | Cierra las posiciones del símbolo y luego vende             |
| `long`                         | `short` (una reversión) | Cierra las posiciones del símbolo y luego compra            |
| el mismo lado que la orden     | `flat` o el mismo lado  | Abre (una entrada, o agrega a una)                          |
| el lado opuesto a la orden     | el mismo                | **Se ignora**: una salida parcial. Se registra, no se opera |

Las salidas parciales no se operan porque no hay una única traducción honesta a MT5: en una cuenta
hedging, un "vende 1 de 3" podría cerrar parte de una posición o abrir una cobertura, y adivinar mal es
peor que no hacer nada. Sal por completo, o deja que los stops tomen ganancias parciales.

<Callout type="warn" title="El volumen es en lotes, no en contratos">
  TradingView dimensiona las estrategias de forex en **unidades**: `{{strategy.order.contracts}}` es
  `100000` para lo que MT5 llama un lote. La plantilla de arriba no envía volumen, así que se usan los
  lotes predeterminados del hook. Envía `volume` solo si está en lotes. Cualquier valor por encima de
  1000 lotes se rechaza como un error de unidades.
</Callout>

### Texto plano [#plain-text]

Acción, símbolo, volumen opcional y luego pares `key=value` opcionales:

```text
buy {{ticker}} 0.10
sell {{ticker}} 0.10 sl=1.1050 tp=1.0900 id={{timenow}}
close {{ticker}}
close_all
```

### Campos [#fields]

| Campo           | También se acepta como      | Significado                                                                                                                     |
| --------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `action`        | `side`, `signal`            | `buy` (`long`), `sell` (`short`), `close` (`exit`), `close_long`, `close_short`, `flat`, `close_all`                            |
| `symbol`        | `ticker`                    | Normalmente `{{ticker}}`. Se asigna como se describe abajo. No hace falta para `close_all`                                      |
| `volume`        | `qty`, `lots`, `contracts`  | Lotes, p. ej. `"0.10"`. Predeterminado: el volumen del hook                                                                     |
| `sl`            | `stopLoss`, `stop_loss`     | Precio absoluto. `0` significa ninguno                                                                                          |
| `tp`            | `takeProfit`, `take_profit` | Precio absoluto. `0` significa ninguno                                                                                          |
| `id`            | `alert_id`                  | Único por alerta; consulta [duplicados](#duplicates)                                                                            |
| `position`      | `market_position`           | `{{strategy.market_position}}`                                                                                                  |
| `prev_position` | `prev_market_position`      | `{{strategy.prev_market_position}}`                                                                                             |
| `comment`       |                             | Se escribe en la orden de MT5 (primeros 17 caracteres, después de la referencia propia de fxapis). Predeterminado `TradingView` |

Los números se pueden enviar como números JSON o como strings. Placeholders que podrías usar:
`{{ticker}}`, `{{exchange}}`, `{{close}}`, `{{time}}`, `{{timenow}}`, `{{interval}}`, y en estrategias
`{{strategy.order.action}}`, `{{strategy.order.contracts}}`, `{{strategy.order.price}}`,
`{{strategy.order.id}}`, `{{strategy.order.comment}}`, `{{strategy.market_position}}`,
`{{strategy.prev_market_position}}`, `{{strategy.position_size}}`.

<Callout title="Pon tus placeholders entre comillas">
  `"volume": {{strategy.order.contracts}}` es JSON válido solo si el placeholder se completa. Entre
  comillas (`"{{…}}"`) siempre lo es. Un mensaje que es casi JSON se rechaza con un motivo que lo dice.
</Callout>

## Símbolos [#symbols]

En orden:

1. **Se quita el prefijo del exchange**: `OANDA:XAUUSD` pasa a ser `XAUUSD` (a menos que lo desactives).
2. **Mapa de símbolos**: si el mapa nombra el símbolo, se usa su valor exactamente: `XAUUSD` → `XAUUSD.a`.
3. **Sufijo**: si no, se agrega el sufijo: con `.a`, `EURUSD` → `EURUSD.a`.

El símbolo en el que se resolvió la alerta aparece en cada entrega, así que un mapeo equivocado es fácil
de detectar.

## Cierres [#closing]

| Acción                                            | Cierra                                                                                               |
| ------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `close`, `flat` (o una estrategia que queda flat) | Todas las posiciones abiertas **del símbolo**, compras y ventas, en cada una de las cuentas del hook |
| `close_long` / `close_short`                      | Solo las compras del símbolo / solo sus ventas                                                       |
| `close_all`                                       | **Todas** las posiciones abiertas en las cuentas del hook, de cualquier símbolo                      |

Cerrar actúa sobre las posiciones que tiene la cuenta, no solo sobre las que abrió una alerta: MT5 no
registra quién abrió una posición de una forma confiable, y que "cerrar XAUUSD" signifique "cerrar el
XAUUSD que veo" es lo que esperan los traders. Primero se leen las posiciones directamente de la
terminal. Cada posición cerrada es su propia orden en tu historial. Si no hay nada abierto, la alerta se
registra como `ignored`.

Desactiva **Act on close alerts** (`"allowClose": false`) si sales solo con stops: las acciones de
cierre se registran entonces como `ignored`, y las reversiones también se ignoran.

Cerrar nunca se rechaza por los límites de tu plan: siempre puedes quedar sin posiciones.

## Duplicados [#duplicates]

TradingView completa `{{timenow}}` una sola vez, cuando se dispara la alerta, así que un reenvío de una
alerta lleva el mismo `id` y una alerta nueva, uno nuevo. fxapis envía cada `id` **una vez**: una
repetición se responde con `200` y `"status": "duplicate"`, se registra y no se opera, incluso si las
copias llegan en el mismo instante.

Sin un `id`, el mismo mensaje dos veces en **60 segundos** se trata como una sola alerta. Eso también
significa que dos alertas idénticas realmente distintas dentro de un minuto se operan una vez: otra razón
para incluir un `id`.

## Seguridad [#security]

* **La URL es la credencial.** 32 bytes aleatorios, mostrada una vez, guardada solo como hash SHA-256.
  Cualquiera que tenga la URL puede operar las cuentas del hook, así que mantenla fuera de capturas de
  pantalla y plantillas compartidas. **Rótala** si se filtra: la URL anterior deja de funcionar de
  inmediato.
* **Only from TradingView** (activado por defecto) rechaza cualquier solicitud que no se envíe desde las
  direcciones de webhook publicadas por TradingView: `52.89.214.238`, `34.212.75.30`, `54.218.53.128`,
  `52.32.178.7`. Desactívalo solo para enviar alertas de prueba desde tu propia máquina.
* **Pausa** un hook para rechazar sus alertas sin tocar TradingView. **Elimínalo** para terminar la URL
  para siempre; sus órdenes se quedan en tu historial.
* Las alertas pasan exactamente por las mismas comprobaciones que una orden de la API: la cuenta debe
  poder operar, tu plan debe permitirlo y no se envía nada mientras el trading esté desactivado para tu
  workspace.
* No pongas secretos en los mensajes de las alertas. El mensaje se guarda (hasta 2 KB) con cada entrega
  para que veas qué llegó; si pegas la URL del hook en un mensaje, se quita antes de guardarlo.

## Solución de problemas [#troubleshooting]

Las alertas que llegan a un hook aparecen en **Console → TradingView → tu hook** (o en
`GET /v1/alert-hooks/{id}/deliveries`) durante 30 días, con un estado y un motivo en palabras simples.
Por encima de 30 alertas por minuto, solo se registra una fila por minuto:

| Estado      | Significado                                                                                                                                         |
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pending`   | Recibida; la orden se está enviando                                                                                                                 |
| `accepted`  | Al menos una orden llegó al broker. El resultado de cada orden —ejecutada, o rechazada por el broker con su motivo— está en el historial de órdenes |
| `rejected`  | No se envió nada. El motivo dice por qué                                                                                                            |
| `duplicate` | Una repetición de una alerta ya recibida                                                                                                            |
| `ignored`   | Entendida y deliberadamente no operada: una salida parcial, nada que cerrar, cierres desactivados, una acción desconocida                           |

Lo que ve TradingView:

| HTTP                       | Significado                                                 |
| -------------------------- | ----------------------------------------------------------- |
| `202`                      | Recibida; la orden se está enviando                         |
| `200`                      | Duplicada o ignorada: no pasará nada más                    |
| `400` `INVALID_ALERT`      | No se pudo leer el mensaje; consulta el motivo              |
| `403` `SENDER_NOT_ALLOWED` | No viene de las direcciones de TradingView                  |
| `404`                      | No existe ese hook: una URL mal escrita, rotada o eliminada |
| `409` `HOOK_DISABLED`      | El hook está en pausa                                       |
| `429` `RATE_LIMITED`       | Más de 30 alertas en un minuto                              |

Causas comunes:

* **No aparece nada en la lista**: la alerta no nos llegó. Revisa que la URL se haya pegado completa,
  que **Webhook URL** esté marcado, y el log de alertas de TradingView. Una URL rotada o eliminada
  responde `404`.
* **`rejected`, no viene de las direcciones de TradingView**: enviaste una prueba con curl u otra
  herramienta. Desactiva **Only from TradingView** mientras pruebas.
* **`rejected`, la cuenta está fuera de línea o no está lista**: la cuenta no estaba conectada. Mantenla
  siempre conectada, o revísala en **Accounts**.
* **El broker rechazó un símbolo desconocido**: el símbolo resuelto aparece en la entrega; agrega una
  entrada al mapa de símbolos o un sufijo.
* **`rejected`, límites del plan**: se agotaron las órdenes del mes, o varias cuentas en un plan sin
  órdenes multicuenta.

## Límites [#limits]

* **30 alertas por minuto por hook.** Por encima de eso, las alertas se rechazan con `429`, y una fila
  lo registra.
* **25 hooks por workspace.**
* **Solo órdenes de mercado** desde alertas, con stop loss y take profit opcionales. Las órdenes
  pendientes van por la [API](/es/trading).
* **Una cuenta por hook en todos los planes**; varias cuentas en los planes con órdenes multicuenta,
  hasta el límite de cuentas por orden del plan.
* Las alertas son **órdenes**: cuentan para las órdenes mensuales del plan.
* Las entregas se conservan **30 días**. Las órdenes se quedan en el historial de órdenes.
* fxapis responde a TradingView de inmediato —TradingView cancela una solicitud de webhook que tarda más
  de tres segundos ([About webhooks](https://www.tradingview.com/support/solutions/43000529348-about-webhooks/),
  revisado el 30 de septiembre de 2026)— y envía la orden justo después, en el orden en que llegaron las
  alertas para ese hook.
