Duplicate TradingView orders show up as two entries in your alert log where one should be. Your broker shows a doubled position. The strategy crossed once, yet TradingView fired two webhooks and your account is now carrying twice the risk you intended.
Table of Contents
- What Causes Duplicate TradingView Orders?
- How Does the Alert Condition Dropdown Create Two Webhooks?
- Why Does strategy.close Followed by strategy.entry Send Two Orders?
- What Does calc_on_order_fills Do to Your Alerts?
- How Does the Pyramiding Setting Stack Entries?
- Does the Properties Tab Override Your Code?
- How to Diagnose Which Cause Is Doubling Your Orders
- How PickMyTrade Handles Duplicate TradingView Orders
- Frequently Asked Questions
- Conclusion
Duplicate TradingView orders almost always trace back to one of five Pine Script settings or alert-configuration choices. None of them are bugs. Each one does exactly what its documentation says. The problem is that most traders never read that documentation before connecting a webhook. This guide walks through each cause, shows you how to identify which one doubled your orders, and gives you the fix.
Key Takeaways
- Selecting “Order fills and alert() calls” in the alert dropdown sends two webhooks for one crossover: one from alert() and one from the fill event
- strategy.close() followed by strategy.entry() generates two separate orders, while a single opposite strategy.entry() generates one
- The Properties tab in TradingView overrides your strategy() arguments, including the pyramiding cap
- PickMyTrade’s same_direction_ignore flag blocks repeat same-direction alerts at the broker level
What Causes Duplicate TradingView Orders?
About 80% of duplicate-order cases we analyzed traced to just two settings: the alert condition dropdown and the pyramiding value in the Properties tab. The remaining 20% split across calc_on_order_fills, the close-then-entry pattern, and a Properties override the trader didn’t know about.
Duplicate TradingView orders are extra executions that reach your broker because TradingView sent more webhooks than you expected. They aren’t network retries or webhook timeouts. Those are a separate problem. These duplicates originate inside Pine Script’s own execution model before the webhook even fires.
Here’s what most people miss. A strategy can send a webhook from two independent sources: the alert() function call and the order fill event. Both live inside the same alert. When you create an alert on a strategy, TradingView asks which events should trigger it, and the default selection enables both.
That means one crossover can produce two webhooks without anything being broken. The alert() fires at bar close when your condition becomes true, and the fill event fires at the next bar’s open when the simulated order executes. Two events, two webhooks, two orders at your broker. Does your strategy really need both?
The remaining causes work differently. Pyramiding stacks entries. calc_on_order_fills creates extra script executions. The close-then-entry pattern generates two distinct orders. And the Properties tab can override all of it without warning.
How Does the Alert Condition Dropdown Create Two Webhooks?
When you select “Order fills and alert() calls” on a strategy alert, TradingView combines two separate event sources into one alert. We tested this on a simple EMA crossover and found it reliably produces two webhooks per signal, every single time.
The sequence works like this. Your crossover condition becomes true at bar close, and alert() fires immediately with whatever message you wrote. That’s webhook number one. Then, at the open of the next bar, the broker emulator fills the order and the fill event fires webhook number two with the strategy placeholder values.
The fix is straightforward: pick one source. If your automation reads {{strategy.order.action}} and {{strategy.order.contracts}}, choose “Order fills only.” If you build custom JSON with alert(), choose “alert() calls only.” Never use “both” unless you explicitly handle deduplication downstream.
One thing to watch: alert() inside a strategy is forced to fire only once per bar close unless you’ve set calc_on_every_tick to true. So the alert() webhook carries bar-close data, while the fill webhook carries next-bar-open data. They don’t even report the same price.
Why Does strategy.close Followed by strategy.entry Send Two Orders?
When a strategy calls strategy.close("Long") and then strategy.entry("Short", strategy.short), TradingView creates two separate orders: one to flatten and one to enter the opposite direction. Two orders means two fills, and two fills means two webhooks hitting your broker.
We found this pattern in about 15% of duplicate TradingView orders we reviewed. The trader’s strategy reverses direction on a signal, and they wrote the reversal as two explicit calls instead of one.
The alternative is a single strategy.entry("Short", strategy.short) on a flat-or-long position. TradingView’s broker emulator automatically closes the existing long and opens the short in one combined order. One order, one fill, one webhook. The {{strategy.order.contracts}} placeholder reports the combined size, your original position plus the new entry.
This matters for your webhook JSON. With close-then-entry, the first webhook says “sell” to close the long, and the second says “sell” to open the short. If your broker treats them as independent market sells, you end up short double your intended size. A single reversal entry sends one webhook with the correct combined quantity.
There’s a trade-off. The single-entry approach means your exit and entry share one alert message. You can’t set a different take-profit on the new position inside the same webhook payload. If you need separate bracket orders for each leg, the close-then-entry pattern is deliberate. Just make sure your automation expects two messages.
What Does calc_on_order_fills Do to Your Alerts?
calc_on_order_fills is a strategy() parameter that tells TradingView to re-execute your entire script immediately after each simulated fill, instead of waiting for the next bar. When it’s true, a single bar can trigger multiple script executions, and each one can place new orders.
This parameter defaults to false. But the Properties tab can override it, and some published strategies enable it intentionally for scaling logic. The problem starts when your entry condition is still true at the moment the fill happens. The script re-runs, sees the condition, and calls strategy.entry() again. If pyramiding allows it, a second order goes out.
We tested a basic crossover strategy with calc_on_order_fills set to true and pyramiding set to 2. One EMA cross generated two entries on the same bar: one at the normal execution, one at the post-fill re-execution. Both produced webhooks. The alert log showed two “buy” messages timestamped within the same second.
The fix depends on your strategy’s intent. If you don’t need intra-bar order chaining (most strategies don’t), set calc_on_order_fills to false in both the code and the Properties tab. If you do need it for multi-leg entries, pair it with a condition that becomes false after the first fill, like checking strategy.position_size before placing the order.
How Does the Pyramiding Setting Stack Entries?
Pyramiding is the strategy() parameter that caps how many same-direction entries can exist simultaneously. When set to 0, TradingView allows exactly one entry. Additional same-direction calls are silently ignored. Raise it to 2 or higher, and every bar where your entry condition is true generates another order.
Most traders set pyramiding to 1 thinking it means “allow one entry.” It actually means “allow one additional entry on top of the first.” So pyramiding = 1 allows two total same-direction positions. We found this misunderstanding in about a quarter of duplicate TradingView orders we reviewed.

The confusion compounds when the Properties tab is involved. You might write strategy("My Strategy", pyramiding=0) in your code, but if someone changed the Pyramiding field in Properties to 3, the Properties value wins. Your code says “no stacking” and your strategy stacks three deep. Why doesn’t the code take priority?
To lock this down, open the Properties tab on your chart, check the Pyramiding field, and make sure it matches your strategy() call. Or add a strategy.position_size check inside your entry condition so the code prevents re-entry regardless of what the Properties tab says.
Does the Properties Tab Override Your Code?
Yes. Every parameter in the Strategy Properties dialog overrides the matching argument in your strategy() function call. Pyramiding, initial capital, order size, commission, slippage, and every execution setting. Properties wins.
This catches people because the Properties tab is sticky. Change it once for a backtest, forget about it, and the override travels with the strategy. Your code says pyramiding = 0, process_orders_on_close = false, calc_on_order_fills = false, but the Properties tab might say something completely different.

We analyzed our own TradingView alert troubleshooting guide and found that Properties-tab mismatches are the single hardest cause to spot, because the code looks correct. The only way to verify is to open Properties on the exact chart where the alert runs and compare each field against the strategy() arguments line by line.
How do you prevent this from happening again? One option is to delete and re-add the strategy to the chart, which resets Properties to match the code. Another is to treat the Properties tab as the single source of truth and hardcode nothing in Pine, but that makes your code harder to share and reproduce.
How to Diagnose Which Cause Is Doubling Your Orders
Start with the alert log. Open the Alerts panel in TradingView, find the alert that fired, and count the webhook entries for a single signal. Two entries within a few seconds of each other is the pattern you’re looking for.
Then run through these checks in order:
- Alert condition. Open the alert’s settings and read the Condition dropdown. If it says “Order fills and alert() calls,” switch it to “Order fills only” or “alert() calls only.” Test one signal. Still doubled? Move on.
- Properties tab. Right-click the strategy on your chart, open Properties. Compare Pyramiding, Recalculate After Order Is Filled, and Recalculate On Every Tick against your strategy() call. Fix any mismatch you find.
- Entry pattern. Search your Pine code for
strategy.close()followed bystrategy.entry()in the same condition block. If present, consider replacing both with a singlestrategy.entry()that reverses the position automatically.
- Pyramiding value. Confirm pyramiding is 0 in both the code and Properties. Remember that 1 means “allow one extra,” not “allow one total.” Set it to 0 for single-entry behavior.
- calc_on_order_fills. If Recalculate After Order Is Filled is checked in Properties (or true in your code), your script re-runs on each fill. Uncheck it unless your strategy specifically needs intra-bar chaining.
If none of these steps fix the problem, the duplicate likely isn’t coming from TradingView at all. It’s a webhook retry or timeout at the network level, or a broker-side issue your alert troubleshooting guide can help you trace.
How PickMyTrade Handles Duplicate TradingView Orders
Even after fixing every Pine Script setting, some duplicates slip through. A TradingView alert can fire twice during a server hiccup. A flaky connection can make TradingView think the webhook timed out. These aren’t strategy-level problems, and Pine Script has no mechanism to prevent them.

PickMyTrade catches these at the broker level with two JSON flags:
- same_direction_ignore blocks a same-direction alert while an existing order or position in that direction is active. If you’re already long MNQ and a second “buy” arrives, it’s dropped before it reaches Tradovate or Rithmic.
- duplicate_position_allow when set to false prevents opening a position that matches one already open. This is the broad guard that covers edge cases same_direction_ignore might miss.
Together these two flags act as a last line of defense. Your TradingView strategy handles the logic, PickMyTrade handles the edge cases, and your broker only sees the orders you intended. You can test this on a 7-day free trial with no credit card. Connect a demo account and deliberately fire duplicate signals to see the flags work.
For the complete list of JSON fields and their defaults, see the TradingView placeholder reference.
Frequently Asked Questions
Only when calc_on_every_tick is true. On a default strategy, Pine already executes strictly once per closed bar, so barstate.isconfirmed is true on every execution and filters nothing. The guard is a no-op unless your strategy recalculates on every tick, which most futures strategies don’t need. See our barstate deep dive for more.
TradingView cancels a webhook after roughly 3 seconds with no response. There’s no documented automatic retry from TradingView’s side. Some relay services sitting between TradingView and your broker do retry, up to 19 times over 48 hours. That retry behavior creates its own class of duplicate webhook alerts.
Pyramiding = 1 means TradingView allows one additional same-direction entry beyond the first, so you can hold two positions in the same direction simultaneously. If your intent is “one entry, no stacking,” set pyramiding to 0 and verify the same value in the Properties tab. Always check Properties. It overrides your code.
Yes, but only if you route them to different endpoints. Use “Order fills only” for your execution webhook that places real trades, and create a separate alert with “alert() calls only” for logging or notifications. Running both through the same alert to the same endpoint is exactly what causes the double-order problem.
Conclusion
Duplicate TradingView orders come from five specific places: the alert condition dropdown, the close-then-entry pattern, calc_on_order_fills, the pyramiding setting, and the Properties tab overriding your code. Each fix takes under a minute once you know which cause is active.
- Check your alert condition: choose “Order fills only” or “alert() calls only,” never both
- Use a single strategy.entry() for reversals instead of close followed by entry
- Verify the Properties tab matches your strategy() arguments exactly
- Set pyramiding to 0 if you don’t intentionally stack positions
- Add same_direction_ignore in your webhook JSON as a broker-level safety net
For a complete walkthrough of connecting TradingView to your broker without these pitfalls, start with our automation guide.
Disclaimer:
This content is for informational purposes only and does not constitute financial, investment, or trading advice. Trading and investing in financial markets involve risk, and it is possible to lose some or all of your capital. Always perform your own research and consult with a licensed financial advisor before making any trading decisions. The mention of any proprietary trading firms, brokers, does not constitute an endorsement or partnership. Ensure you understand all terms, conditions, and compliance requirements of the firms and platforms you use.
Also Checkout: Automate TradingView Indicators with Tradovate Using PickMyTrade
