Skip to main content

Timing & Idempotency

Three fields that govern when a payload runs and how often TVH retries on transient errors.

TL;DR
  • alertTimestamp is the single most important field for production setups. It's the idempotency key. TVH stores one lock row per (token, exchange/apiKey, alertTimestamp) triple — duplicate triples are rejected for as long as the lock row exists.
  • Recommended Pine value: "{{ticker}}-{{timenow}}".
  • delay pauses the signal before forwarding to the exchange (max 604800 = 7 days). Useful for "wait, then act" patterns.
  • retries controls how many times TVH re-sends an order on a Binance overload response (default 1, max 10).

Quick reference table

PropertyTypeRequiredDefaultDescription
delayintno0Seconds to wait before TVH forwards the signal to the exchange. Useful for staggered exits or letting the spread settle after news.
retriesintno1How many times TVH re-sends an order when Binance returns an overload / server-busy response. Binance-specific overload guard, not a general cross-exchange retry; does not retry hard rejections or IP bans. Capped at 10.
alertTimestampstringnoIdempotency key. TVH builds a deduplication key from (token, apiKey-or-exchange, alertTimestamp) the first time it processes the payload; a later payload with the same triple is recognised as a duplicate and silently dropped. Recommended Pine value: "{{ticker}}-{{timenow}}".

alertTimestamp — the idempotency key

TradingView can retry a webhook on transient network errors. The same alert can also be re-fired by an alertcondition() rule that triggers on every bar close in volatile conditions. Without a deduplication mechanism, a single intended fill can become two or three.

alertTimestamp solves this. TVH builds a deduplication key from (token, apiKey-or-exchange, alertTimestamp) the first time it sees a payload. A duplicate payload — same token, same apiKey/exchange, same alertTimestamp — produces the same key, gets recognised as already processed, and is silently dropped.

alertcondition(
longSignal,
title="Long Entry",
message='{"exchange":"binance-futures","pair":"{{ticker}}","apiKey":"binance-futures-main","isBuy":true,"unitsType":"percent","unitsPercent":2,"alertTimestamp":"{{ticker}}-{{timenow}}","token":"<token>"}'
)

{{ticker}} is the symbol (e.g. BTCUSDT); {{timenow}} is the millisecond Unix timestamp of the bar. The concatenation produces a value like:

BTCUSDT-1715900400000

Unique per bar, per pair. If TradingView retries the same alert, the timestamp matches and TVH drops the duplicate.

Why {{timenow}} and not {{time}}?

  • {{time}} is the bar's open time. Two alertcondition calls on the same bar share the same {{time}} — useful when you want dedup across the same bar.
  • {{timenow}} is the current time when the alert fires. Different fills on the same bar get different values.

Pick the one that matches your "what counts as a duplicate" definition. For most setups, {{timenow}} is right.

How long the lock lasts

Deduplication is effectively permanent: as long as TVH retains the record, replaying the exact same (token, apiKey, alertTimestamp) triple is rejected. In practice that means:

  • A retry from TradingView seconds after the original always dedups.
  • Re-using a static alertTimestamp string across days dedups — only the first run gets through.
  • Treat the dedup as permanent for the lifetime of any given alert template.

The lock row key includes the apiKey (or, if blank, the exchange slug) as a discriminator. The same alertTimestamp value sent to two different apiKeys is not dedup'd — both go through. This is intentional: copy-trade fan-out maps one master signal to many follower signals, each with its own apiKey.

delay — staggered execution

{
"delay": 10
}

Wait 10 seconds, then forward the signal to the exchange. The webhook accepts the payload immediately, but the actual exchange submission is delayed.

Use cases:

  • Spread settles after news. A scheduled news release widens spreads briefly. Delay the entry by 10–30 s so it fills closer to the new fair value.
  • Staggered legs. Two TradingView alerts fire on the same bar (e.g. two pairs). Use different delay values to space the exchange calls apart and avoid rate limits.
  • Bias confirmation. Pine signal fires on bar close; you want to wait for the next bar's first tick to confirm. delay: 60 (on a 1-minute chart) buys you the confirmation window.

Range: 0 to 604800 seconds (= 7 days). Practical maxes are usually under 300 s.

Negative delay for email override. A value of -1 is used internally for email-driven signals — when present, TVH dispatches the trade without the default 5-second delay applied to other email-path signals. You should not set this manually; it's left untouched on direct webhook payloads. See Email Backup.

retries — transient-error backoff

{
"retries": 3
}

When a Binance order call comes back with an overload / server-busy response, TVH re-sends it up to retries times before giving up. The field exists specifically for Binance's busy-server bursts (its in-code comment is literally "retries for overload on binance"). It does not retry hard rejections like bad parameters or an IP ban, and it is not a general cross-exchange retry layer.

Default is 1. That's enough for the vast majority of cases. Crank it up to 3 or 5 for setups that absolutely must land — retries: 5 adds at most a few seconds of latency on a healthy exchange. The value is capped at 10; higher numbers are clamped.

The retry uses a short backoff between attempts (a small increasing delay). The exact schedule is internal and may evolve; you don't tune it.

Not a substitute for alertTimestamp. Retries on TVH's side are different from retries on TradingView's side. The first protects against exchange flakiness; the second is what alertTimestamp dedups.

Detail per property

alertTimestamp

AttributeValue
Typestring
Requiredno (but strongly recommended in production)
Default""
TV placeholder compatibleyes

Idempotency key. TVH inserts a lock row keyed on (token, apiKey-or-exchange, alertTimestamp) when the trade-queue worker first processes the payload. Any later payload that produces the same key is recognised as a duplicate and silently dropped. The lock row persists; treat dedup as permanent per template.

delay

AttributeValue
Typeint (seconds)
Requiredno
Default0
TV placeholder compatibleno

Seconds to wait before forwarding to the exchange. Max 604800.

retries

AttributeValue
Typeint
Requiredno
Default1
TV placeholder compatibleno

How many times TVH re-sends an order on a Binance overload (server-busy) response. Capped at 10. Not a general cross-exchange retry.

Common mistakes

  • No alertTimestamp in production. A TradingView retry doubles the position. Always set it.
  • Same alertTimestamp across pairs. "{{timenow}}" alone (without {{ticker}}-) collides when two pairs fire on the same bar. Prefix with the ticker.
  • delay > 60 on a strategy alert. TradingView strategy alerts trigger on bar close and Pine doesn't know about the delay — your Pine SL might fire on the next bar before the entry has even been submitted. Keep delay short for strategy-mode alerts.

Next

Math Expressions — the dedicated reference for the stopLossExpression / takeProfitExpression evaluator.