Guide

Why Your Pine Script Strategy Isn't Taking Trades

The script compiles, the Strategy Tester opens, and the trade list is empty. Here are the causes in the order you should check them.

13 min read

This is the most frustrating failure in Pine Script because there is no error to search for. The script compiled, the Strategy Tester loaded, and the List of Trades is empty. Nothing tells you what went wrong, so people usually start changing the entry logic, which is the one thing that is often already correct.

Short answer

When a Pine Script strategy compiles but places no orders, the cause is almost always one of five things: the entry condition never evaluates to true on the dataset, the order size cannot be afforded from the strategy's capital, the order call sits in a scope that never executes, the v6 margin defaults are rejecting the order, or the code still uses the removed when parameter. Check them in that order, because the first two account for the majority of cases and both are configuration rather than logic.

Key facts

  • A strategy that places no orders is usually not raising an error, so the Strategy Tester gives no diagnostic message. The absence of an error is itself the clue that the code ran and the conditions were simply never met.
  • TradingView's default initial capital for a strategy is 1,000,000, and TradingView notes you may need to increase this value for trades to occur on certain symbols, because one unit of some instruments costs more than the available capital.
  • Pine Script offers three default order-size methods through default_qty_type: a fixed contract quantity (strategy.fixed), a cash amount (strategy.cash), and a percentage of equity (strategy.percent_of_equity).
  • calc_on_every_tick defaults to false, which means a strategy calculates only on the close of each bar rather than on every realtime tick.
  • In Pine v6 the default long and short margin percentage is 100, and strategies enforce position-size limits by default. If equity falls too far, existing positions can be liquidated by margin calls.
  • The when parameter was deprecated in v5 and removed in v6 from strategy.entry(), strategy.order(), strategy.exit(), strategy.close(), strategy.close_all(), strategy.cancel(), and strategy.cancel_all(). Conditional orders now require an if block.
  • strategy.entry() with the same order ID as an open position modifies that position rather than opening an additional one, so repeated entries do not necessarily produce repeated trades.
CheckWhat to look atFix if this is the cause
1. Condition never truePlot the condition as a shape or log itLoosen the condition or fix the comparison
2. Order size vs capitalInitial capital and default_qty_typeRaise capital or switch sizing method
3. Scope of the order callIs the call inside a block that runs?Move the call into a reachable if block
4. v6 margin defaultsmargin_long and margin_shortSize positions to fit or set margin explicitly
5. Removed when parameterSearch the source for "when ="Replace with an if block

Check the condition before you change it

The instinct is to rewrite the entry logic. Resist it, because you have no evidence yet that the logic is wrong. What you know is that the order never fired, and that can happen with a perfectly correct condition. So make the condition visible before editing it.

The fastest way is to plot it. Convert the boolean into a shape on the chart and look at whether it ever appears. If the marker never shows anywhere in the dataset, the condition genuinely never became true and the logic is the problem. If markers appear but no trades exist next to them, the condition is fine and your problem is somewhere in the order path. That single test splits the investigation in half.

Common reasons a condition never fires include comparing values that can never cross because one is derived from the other, requiring several filters to align simultaneously when they rarely do, using a strict greater-than where the values are equal, or comparing a value against a threshold on the wrong scale. Pine v6 also removed implicit numeric-to-boolean casting, so a numeric expression used directly as a condition is now a compile error rather than a silent truthiness check.

pine
//@version=6
strategy("Diagnose entries", overlay = true)

fast = ta.sma(close, 10)
slow = ta.sma(close, 30)
longCondition = ta.crossover(fast, slow)

// Make the condition visible before editing it.
plotshape(longCondition, "Long signal", shape.triangleup, location.belowbar)
if barstate.isconfirmed and longCondition
    log.info("Long condition true at bar {0}", bar_index)

if longCondition
    strategy.entry("Long", strategy.long)

If the triangles appear and the log fills but the trade list stays empty, you have proved the condition works and can move on to sizing and scope. That is a much stronger position than guessing at thresholds.

Order size against available capital

This is the cause people find last and should check second. TradingView sets the default initial capital for a strategy to 1,000,000 and explicitly notes that you may need to increase it for trades to occur on certain symbols. The reason is arithmetic: if the strategy cannot afford the quantity your sizing rule requests, there is no order to place.

It bites hardest on high-priced instruments and on contracts with large multipliers. A fixed quantity that is trivial on a low-priced equity can exceed available capital on an index future. The same applies in reverse on instruments where the minimum order increment is larger than the size your percentage-of-equity rule computes, which can round down to nothing.

Pine gives you three default sizing methods, and choosing the right one often resolves the problem outright. strategy.fixed uses a contract quantity, strategy.cash uses a cash amount, and strategy.percent_of_equity sizes from equity. Percentage of equity adapts to the instrument automatically, which makes it a good diagnostic choice: if trades appear when you switch to a modest percentage of equity, your original problem was sizing rather than logic.

pine
//@version=6
// Sizing from equity adapts across instruments and price levels.
strategy("Equity sizing",
     overlay = true,
     initial_capital = 10000,
     default_qty_type = strategy.percent_of_equity,
     default_qty_value = 10)

Verify the values in the Strategy Tester settings as well as in code. Chart-level properties can override what you expect from the declaration, and a mismatch between the two is a common source of "it works on my chart" confusion.

Scope: is the order call actually reachable?

An order call that never executes produces exactly the same symptom as a condition that is never true. The distinction matters because the fix is different. Look at where the call sits. If it is inside a user-defined function that nothing calls, inside a branch guarded by a second condition you forgot about, or inside a block that only runs under a chart state that never occurs, the entry logic will look fine and still never place an order.

A related trap is order-ID reuse. strategy.entry() with an ID matching an already-open position modifies that position rather than adding a second one. If you expected a sequence of separate trades and see one, the orders are being consolidated, not skipped. Distinct IDs, or an explicit pyramiding setting, change that behavior.

Bar state is the third variable. calc_on_every_tick defaults to false, so a strategy evaluates on bar close. Code written with the assumption that it runs on every tick, or guarded by a realtime-only bar state, can behave very differently from what you expect on historical bars. If your condition depends on barstate values, confirm that the state you are gating on actually occurs during the historical replay the Strategy Tester performs.

The v6 margin defaults, and the removed when parameter

Pine v6 changed strategy defaults in ways that can silently suppress orders in code migrated from v5. The default long and short margin percentage is now 100, and strategies enforce position-size limits by default rather than ignoring available funds. A strategy that previously opened positions larger than its capital will now decline to do so, and if equity falls far enough, existing positions can be closed by margin calls. TradingView also documents that v6 avoids attempting orders with negative quantity in these conditions.

This is a correctness improvement, not a bug, but it changes results. If a v5 strategy produced trades and the same code in v6 does not, compare the margin settings before touching the entry rules. Setting margin explicitly is a legitimate choice as long as you make it deliberately and understand that you are modelling leverage.

The removed when parameter is the other migration trap, and it is the easiest to check. Search the source for "when =". In v5 that parameter was deprecated; in v6 it is removed from every applicable strategy function. Conditional orders now require an if block, which is clearer anyway because the control flow is visible.

pine
// v5 pattern, no longer valid in v6
// strategy.entry("Long", strategy.long, when = longCondition)

// v6 equivalent
if longCondition
    strategy.entry("Long", strategy.long)

Move only the condition into the if block. Do not take the opportunity to adjust the rule at the same time, or you will not know whether a change in results came from the migration or from your edit.

A diagnostic order that saves time

Work from cheapest test to most expensive. First, plot the condition and confirm it fires. Second, check initial capital and sizing, and try a modest percentage of equity as a control. Third, confirm the order call is reachable and the order IDs are what you intend. Fourth, inspect margin settings if the code came from v5. Fifth, search for the removed when parameter.

Change one variable at a time and re-read the Strategy Tester between changes. The reason is diagnostic, not stylistic: if you adjust the threshold, the sizing, and the margin together and trades appear, you have learned nothing about the cause and you may have introduced a new problem to compensate for the original one.

Keep a note of what you ruled out. An empty trade list has a handful of causes, and once you have eliminated the condition and the sizing, the remaining possibilities are narrow. That written record is also what makes the next occurrence quick, because this failure tends to recur whenever you move a strategy to a new instrument.

Why a focused workflow matters for silent failures

Silent failures are the worst case for a general chat assistant. There is no error text to paste, so the only thing you can hand over is the whole script and a description of the symptom. The typical response is a rewritten strategy, which may produce trades for reasons you cannot identify, because the entry logic, the sizing, and the declaration may all have changed at once. You end up with something that works and no understanding of why.

PineScripter is our product, and it is built for the opposite pattern. It retrieves the Pine Script v5 and v6 manuals as context, so proposals reference documented behavior such as the v6 margin defaults or the removed when parameter instead of guessing. Its edits target the specific lines involved and appear as a reviewable diff, which is what you want when the question is "which one of five configuration values suppressed my orders".

The honest limit is that no tool can tell you whether your trading rule is a good one, and none of this is a claim about results. What a focused workflow does is keep the investigation orderly and the changes small, so when trades finally appear you know exactly which change produced them. Verify the final behavior yourself in the Strategy Tester on the instrument you actually intend to use.

Changing one configuration value at a time keeps the cause identifiable

Frequently asked questions

Why does my Pine Script strategy compile but show no trades?

The five usual causes are: the entry condition never becomes true on the dataset, the order size cannot be afforded from the strategy's capital, the order call sits in a scope that never executes, the Pine v6 margin defaults are rejecting the order, or the code still uses the when parameter that v6 removed. Check them in that order, because the first two are the most common and both are configuration rather than logic.

What is the default initial capital for a TradingView strategy?

TradingView's default initial capital for a strategy is 1,000,000. TradingView notes that you may need to increase this value for trades to occur on certain symbols, because the cost of a single unit of some instruments can exceed the capital available to the strategy.

How do I check whether my entry condition is ever true?

Plot the boolean condition as a shape with plotshape() and look for markers across the dataset, and optionally log it with log.info() including the bar index. If no marker ever appears, the condition is the problem. If markers appear but no trades do, the condition is fine and the cause is in the order path, such as sizing, scope, or margin.

Why did my strategy stop taking trades after upgrading to Pine v6?

Pine v6 sets the default long and short margin percentage to 100 and enforces position-size limits by default, so a strategy that previously opened positions larger than its capital will now decline to. v6 also removed the when parameter from strategy functions, which requires conditional orders to use an if block instead. Compare margin settings and search for "when =" before changing entry rules.

Does calc_on_every_tick affect whether trades appear?

It can. calc_on_every_tick defaults to false, which means the strategy calculates on the close of each bar rather than on every realtime tick. Logic written on the assumption of tick-by-tick evaluation, or gated on a realtime-only bar state, may behave differently during the historical replay the Strategy Tester performs.

Why does my strategy only open one trade instead of several?

strategy.entry() called with the same order ID as an already-open position modifies that position rather than opening an additional one. Use distinct order IDs, or configure pyramiding, if you intend multiple concurrent entries.

The practical takeaway

An empty trade list is a configuration puzzle far more often than a logic failure, so resist rewriting the entry rule first. Prove the condition fires by plotting it, then check capital and sizing, reachability of the order call, the v6 margin defaults, and any leftover when parameter. Fix one thing at a time so that when trades appear, you know which change produced them.

For the specific problem of changing one configuration value at a time without a full rewrite, PineScripter is our product, and its line-level edits plus diff view are built for exactly that kind of narrow, auditable change.

Sources

Related reading: Pine Script v6 upgrade errors, position sizing and risk rules in code, how TradingView backtesting works, runtime errors on the chart.

Disclaimer: PineScripter is a coding tool for Pine Script development. It does not provide financial advice and does not guarantee trading profits. Always backtest strategies thoroughly and understand the risks before live trading.