Stale-alert guard#
TradingView can — and occasionally does — replay alerts. The most common causes:
- A TradingView server hiccup retries an alert that already arrived.
- A user re-runs a saved alert from the alert history.
- An indicator misbehaves and re-fires the same alert in quick succession.
- A long-queued alert is delivered minutes late after an outage.
The stale-alert guard is HookTrader's first line of defence.
How it works#
Some webhook payloads may include a ts (timestamp). When present, HookTrader compares it to the server clock:
The freshness window defaults to 30 seconds. Rejected stale alerts:
- Are logged to the strategy's webhook log with reason
stale_alert. - Do not raise a user notification (they're considered noise).
- Do not affect any open trade.
Why timestamps?#
A 30-second freshness window strikes a balance:
- Long enough to tolerate normal network latency and processing delays.
- Short enough that a replay 5 minutes later (the most common failure mode) is always rejected.
- Cheap to verify — no per-alert state needed, just the payload's own
ts.
What it doesn't guard against#
The stale guard catches replays, but not legitimately-fast duplicates. For those:
- Per-token rate limiting caps how many alerts per second a single webhook can fire. The bucket is configured server-side and surfaces as
429 Too Many Requests. - HookTrader enforces invariants like "one active trade per webhook" and "one symbol across all of a user's strategies" — duplicate entry alerts while a trade is already open are silently ignored.
So:
| Scenario | Caught by |
|---|---|
| Same alert replayed 5 min later | Stale-alert guard |
| Same alert fired 10× in 100ms | Rate limit |
| Entry alert when trade already open | HookTrader (silent ignore) |
| Wrong-symbol alert on a pair-locked strategy | HookTrader (rejected) |
Tuning#
The freshness window is a global setting; it isn't user-configurable today. If you're running an exotic setup where alerts legitimately arrive minutes late (e.g. an indicator that batches signals), open a feature request rather than disabling the guard.
Related#
- Alert payload (v2) — where
tslives in the envelope. - Troubleshooting → Rejected trades — full list of rejection reasons.