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.
alertTimestampstringno—Idempotency 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":"percentBalance","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.