Risk Management · Position Sizing

Dynamic Position Sizing for TradingView Webhook Bots
Percent-of-Equity vs Fixed Quantity

2026-07-22·9 min read

Say your backtest runs with a $100,000 initial_capital, and default_qty_type is set to strategy.percent_of_equity at 10%. Your real exchange account has $2,000 in it. When the alert fires and the webhook lands on your execution server, what quantity does it actually send?

The short answer: TradingView computes that quantity as 10% of strategy.equity — and strategy.equity is a number the Pine strategy simulates entirely on TradingView's servers. It has no idea your real account holds $2,000. The quantity in the alert is sized off the backtest's internal balance, not the balance sitting at your exchange.

That single line of the strategy declaration is the thing worth getting right, and it's exactly the kind of detail an AI will pick for you silently if you don't say which one you want. So this post is short on syntax and long on two things: how to tell an AI which sizing behaviour you actually need, and how to check the code it gave you before real money is involved. There's a copy-paste prompt further down.

This is the core gap this article covers: TradingView's official documentation defines exactly how default_qty_type and strategy.equity work. It does not, anywhere, discuss how that relates to your real exchange balance — because there is no connection. That gap is the entire reason position sizing trips up people wiring TradingView alerts into live execution.

The one setting that decides your order size

When you declare a strategy, the strategy() call takes a default_qty_type parameter with exactly three legal values, plus a default_qty_value that means something different under each one. Find that line in whatever code you've been handed — it's near the top — and read it against this table. That's the whole check.

default_qty_typeUnit of default_qty_valueWhat it means
strategy.fixedContracts / shares / lotsThe default. A flat number of units per entry.
strategy.cashAccount currency amountA cash amount in strategy.account_currency. Quantity is derived as default_qty_value / close — TradingView's own docs give the example: at a $5 close price, a value of 50 yields qty = 50 / 5 = 10.
strategy.percent_of_equityPercentage (0–100)A percentage of strategy.equity — the strategy's current simulated equity — used to size the entry.

Source: Pine Script Reference Manual v6, strategy() and the three default_qty_type constants (verified July 2026).

One more detail worth knowing: if a strategy.entry() or strategy.order() call passes an explicit, non-na qty argument, that value overrides default_qty_type/default_qty_value entirely for that order — the strategy-level default only applies when no qty is given on the call itself. TradingView's own docs demonstrate this with an example where a strategy declares default_qty_type = strategy.cash but the entry call still supplies its own qty, and the default setting is simply ignored for that trade.

That override matters when you're reviewing generated code, because it means the declaration line at the top can say one thing while the order calls quietly do another. It's worth asking as a flat question: "Does any entry or order call in this script pass its own qty? List them."

Why "10% of equity" isn't 10% of your money

The official definition, verbatim, from the Pine Script Reference Manual — this is here so you recognize it, not so you memorize it:

text
strategy.equity = strategy.initial_capital + strategy.netprofit + strategy.openprofit

netprofit is cumulative realized profit and loss from closed trades; openprofit is unrealized profit and loss on whatever position is currently open. Both change on every bar as trades close and prices move, which makes strategy.equity a moving series — it can be a different value on almost every bar.

This is also why percent_of_equity sizing compounds by construction. A default_qty_value of 10 always means "10% of whatever strategy.equity is on this bar." After a run of profitable closed trades, equity is larger, so the same 10% now resolves to a bigger absolute quantity. After losses, the opposite happens. TradingView's own Commission Demo example strategy uses exactly this setting (default_qty_value = 2, default_qty_type = strategy.percent_of_equity) specifically to illustrate a position that scales with equity as it changes.

Where the official docs stop
Everything above is TradingView's own documented behavior, quoted directly. What the documentation does not say anywhere is how this simulated strategy.equity relates to the balance in your actual exchange account. Based on the definition above — initial_capital is a number you type into the strategy() declaration, and netprofit/openprofit are simulated purely on TradingView's servers — it can reasonably be inferred that strategy.equity has no connection to your real account balance. That's an inference from the official definition, not a line TradingView states directly.

Which one to ask for, and what each one costs you

Neither mode is "correct." They optimize for different things, and the trade-off is worth seeing side by side rather than guessing which one a backtest happens to look better with. Read this as a menu: whichever column you want is the one you name in your prompt.

percent_of_equityfixed
Order size scales as equity changes
Order size is predictable in absolute units ahead of time
Depends on a simulated internal balance you don't control at runtime
Needs manual resizing as your real account grows or shrinks
Backtest and live orders can diverge if simulated equity and real balance are far apart

Read the trade-off as what each one depends on: percent_of_equity scales, but only against a number TradingView simulates internally; fixed is predictable, but never adjusts to your account on its own. That dependency is what decides whether the number in your webhook payload means what you think it means.

The prompts: asking for it, then checking it

Asking for it

The version below asks for fixed quantity and pushes the sizing decision to the execution side, which is the setup that doesn't depend on a simulated balance. If you want the opposite, swap the sizing paragraph — the point is that you say which one, and say why, rather than leaving it to be picked for you:

text
Write me a Pine Script v6 strategy for TradingView. It will fire a webhook into
a live exchange account.

Strategy logic: [describe your entries and exits in plain language]

Position sizing — this part is not negotiable:

- Use default_qty_type = strategy.fixed with default_qty_value = 1.
  Do NOT use strategy.percent_of_equity. Reason: percent_of_equity sizes the
  order off strategy.equity, which is a simulated backtest balance, and my
  real exchange account is a different size. I do not want the backtest's
  number reaching my exchange.

- Do not pass a qty argument on any strategy.entry() or strategy.order() call
  unless I explicitly ask for one. If you do pass one anywhere, say so.

- The alert message must be one single line of valid JSON containing the
  action ({{strategy.order.action}}) plus these fields and nothing else:
  [paste the field list your receiver expects]
  Do NOT include {{strategy.order.contracts}} — my execution server decides
  the quantity, not TradingView.

Finish by telling me in one line each: what default_qty_type you used, what
default_qty_value means under that setting, and whether any order call
overrides them.

The reason for spelling out the "why" in the sizing bullet isn't politeness — it stops the reply from helpfully switching you back to percent_of_equity because the backtest curve looks nicer that way.

Checking what you got back

Paste the code back with this. It's four questions, and you already know what three of the answers should be from the sections above — which is the point:

text
Here is my strategy. Answer these before changing anything:

1. What is default_qty_type set to, and what does default_qty_value mean
   under that setting?

2. Does any strategy.entry() or strategy.order() call pass its own qty?
   List them — those override the strategy-level default for that order.

3. If I run this with initial_capital = 100000 but my real exchange account
   holds 2000, what number ends up in {{strategy.order.contracts}}?

4. Which fields in my alert message are derived from the simulated backtest
   balance rather than from my real account?

[paste your script here]

Question 3 is the one to watch. An answer that works through the quantity from initial_capital understands the setup. An answer that says the strategy will size against your $2,000 does not, and anything else in that reply is worth re-checking.

Telling the AI what to put in the alert message

These are the placeholders TradingView's official docs list for strategy order-fill events — the only place quantity data is exposed to an alert message. You're not writing these by hand; you're naming the ones you want in your prompt, and checking that what came back uses those and only those:

PlaceholderWhat it resolves to
{{strategy.order.contracts}}The quantity filled on that specific order
{{strategy.position_size}}Current position size at the moment of trigger, signed (+long / −short)
{{strategy.market_position_size}}Current position size, absolute value
{{strategy.prev_market_position_size}}Previous position size, absolute value
{{strategy.order.action}}"buy" or "sell"
{{strategy.order.price}}Fill price
{{strategy.order.alert_message}}Custom text passed to the alert_message argument of that specific strategy.entry()/strategy.exit()/strategy.order() call

Strategy order-fill event placeholders only — not usable inside alertcondition() or standalone alert() messages. Source: Pine Script user manual, Strategies / Strategy alerts (verified July 2026).

Worth flagging on {{strategy.order.alert_message}}: the official docs are explicit that this placeholder is only replaced with your custom text if the specific order-generating call actually passed an alert_message argument. If your strategy has several strategy.entry()/strategy.order() calls and only some of them set alert_message, the placeholder resolves to an empty string for the ones that didn't.

Which is a specific, checkable thing to ask for: "If you use {{strategy.order.alert_message}} anywhere in the alert message, confirm that every single order call in this script passes an alert_message argument." An empty field in a JSON payload is the kind of thing that breaks a receiver at 3am rather than at review time.

So where does this JSON actually go?
Three different places, and picking the wrong one is how you end up with an alert that fires into an empty payload:
One: the alert() call in the code. The message is assembled by the script itself, so you don't retype it in the dialog.
Two: the alert_message= argument on an order function. That text only surfaces when an order-fill event fires and the message uses {{strategy.order.alert_message}}.
Three: the Message field in TradingView's Create Alert dialog. This is the only place {{strategy.*}} placeholders work, and only when the alert was created from a strategy.
The click-by-click version — chart top-right clock, Add Alert, Condition = your strategy, Notifications tab, Webhook URL — is walked through in Writing Pine Script With Claude.

The one decision no AI can make for you

Given that percent_of_equity is computed against a simulated balance, and fixed/cash don't know your account size at all, there's a real design decision in any TradingView-to-exchange automation: does TradingView decide the final order quantity, or does the execution server?

1
Do you want order size to move automatically as your account balance changes?
YesYou need something computing a percentage of a balance on every signal — either TradingView's simulated equity, or your execution server querying your real account.
NoA fixed quantity or fixed cash amount per signal is simpler and needs no balance lookup at all.
2
Is your real exchange balance meaningfully different from the strategy's initial_capital?
Yes, quite differentSending TradingView's percent_of_equity-derived qty straight to your exchange means it's sized off the wrong balance — it needs to be re-derived on the execution side against your real account.
No, roughly alignedThe gap is smaller today, but initial_capital is a number you set once and equity keeps compounding in the backtest — worth re-checking as the two diverge over time.
3
Which side should own the final sizing decision?
TradingView sideSend a pre-computed number via a placeholder like {{strategy.order.contracts}} and forward it as-is — simplest, but it's the backtest's number.
Execution sideSend direction and let the receiving server size the order against your actual, current exchange balance at the moment it fires.

This is where the two layers of the problem meet. Everything above is about how TradingView decides what number to put in the alert. Once that number — or just a signal direction — lands on an execution server, there's a second, separate layer: how that server turns it into an actual exchange order, including how leverage interacts with margin and notional size. That second layer is covered in detail in our qty_type semantic trap article — worth reading once you've settled who computes the quantity, since it explains what happens to that number after it arrives.

TVSBot's execution side, for example, resolves quantity at order time using one of five sizing modes (fixed / usdt / percent / margin_pct / margin_usdt) rather than simply forwarding a number computed from a backtest's simulated equity. Two of those — percent and margin_pct — query your real, current exchange balance at order time and size from that. usdt and margin_usdt convert a USDT figure you specify using the live ticker price, and fixed sends the coin quantity you gave it as-is.

To see what a mode actually resolves to before real capital is at stake, dry-run mode runs the strategy against a virtual balance and shows the number that would have been sent. Per-account risk settings — max amount per trade, max percent per trade, max open positions, a daily loss limit, a max leverage cap — plus a one-click kill switch sit around whatever sizing logic feeds the order.

FAQ

Does percent_of_equity automatically account for my real exchange balance?
No. strategy.percent_of_equity sizes orders as a percentage of strategy.equity, which is officially defined as initial_capital + netprofit + openprofit — all three of those are simulated inside the Pine strategy, not looked up from your exchange account. TradingView's docs don't describe any mechanism for reading a real account balance.
Can I just tell the AI to size positions off my real exchange balance?
Not inside Pine. TradingView's documentation doesn't describe any mechanism for a strategy to read a real account balance, so no phrasing of the request changes that. What you'll get back is a strategy sizing off strategy.equity — possibly with initial_capital set to a number that happens to match your account today, which drifts apart again as soon as the simulated equity compounds. Sizing against a live balance has to happen after the alert, on the execution side.
If I set default_qty_type to strategy.fixed, will the quantity ever change on its own?
No. strategy.fixed uses a flat number of contracts/shares/lots defined by default_qty_value. It won't grow or shrink with account performance unless you change the input yourself.
Can I pass qty directly in strategy.entry() instead of relying on default_qty_type?
Yes — a non-na qty argument on strategy.entry() or strategy.order() takes precedence over the strategy-level default_qty_type/default_qty_value settings entirely, for that specific order.
Which placeholder gives me the quantity that was actually filled?
{{strategy.order.contracts}} resolves to the quantity filled on that specific order. It's only available in strategy order-fill event alerts, not in alertcondition() or standalone alert() messages.
Should quantity be decided on the TradingView side or the execution side?
Both are workable, and this article doesn't recommend one for profitability — it's a mechanism trade-off. Deciding it on TradingView's side is simpler to wire up. Deciding it on the execution side means the sizing is computed against your real, current account balance rather than a simulated one, which matters more the further your live balance has drifted from the strategy's initial_capital.

Get started

Ready to ship what you just learned?

TVSBot is a non-custodial bridge from TradingView alerts to 7 exchanges — your API keys, your funds. Percent-based sizing modes resolve against your real, live balance at order time, with dry-run testing and per-account risk limits.

Start free