TradingView retried your webhook. Titan blocked the duplicate.
Anything but a 2xx response makes TradingView resend the alert — their docs say so — and a resent alert is a doubled position. Duplicate detection is Titan’s first check, before anything else runs. Below: both receipts. The forward and the block.
TradingView’s webhook documentation is explicit: if your endpoint does not answer with a 2xx status code, the alert is resent. Same payload, seconds apart. All it takes is a timeout or a cold start on your side, and your endpoint receives the same BUY twice. Your bot cannot tell the deliveries apart, because they are byte-for-byte the same alert.
If that endpoint submits orders, the retry is a double fill: twice the position you sized for, discovered whenever you next look at your account.
These are two real decisions from a sandbox demo account — the same signal id, delivered twice through the normal webhook path. First delivery:
Second delivery of the same alert, moments later:
Honesty note: the forwarded decision is hash-chained and Bitcoin-anchored — it went through full evaluation. The duplicate was refused before evaluation, so its refusal is recorded with a trace id but is not part of the anchored chain. We could pretend otherwise; the receipts would catch us.
Duplicate detection runs before everything else — market hours, position limits, and price checks all come later — because a duplicate that gets any further is pure downside. There is no strategy in which acting on the same alert twice was the intent. Titan answers every delivery with a 2xx (so TradingView stops retrying), forwards the first, refuses the rest, and gives you a receipt for each decision either way.
Titan proves what your strategy said, when it said it, and what the safety checks decided. It does not prove you made money.
Titan does not manage open-position risk after a fill, does not hold funds, does not store broker credentials, and does not submit orders — execution stays in your hands, on your machine. Works with Alpaca today.