Pine Script v6: Add Commission and Slippage to Strategies
By HorizonAI Team · 12 min read · Intermediate
How to Add Commission and Slippage to a Pine Script Strategy in v6
An EMA crossover can look excellent in TradingView's Strategy Tester until every entry and exit pays a fee and gives up a few ticks. That gap doesn't mean the crossover code is broken. It means the backtest is using frictionless fills that your actual orders won't receive.
Short answer: set commission_type, commission_value, and slippage in your Pine Script v6 strategy() declaration. Commission charges each filled order according to a percentage, flat order fee, or per-contract fee. Slippage is a whole number of minimum price increments, or ticks, applied adversely to eligible simulated fills.
Use a strategy(), not an indicator(), then set deliberate capital and quantity assumptions. Configure limit-order verification separately in Strategy Properties. It controls whether price must move beyond a limit price before that limit is considered filled, which is not the same thing as slippage.
What commission and slippage actually change
A TradingView indicator calculates and draws values. A strategy also submits simulated orders to TradingView's broker emulator, so it can model starting capital, order sizing, commissions, slippage, and fill rules. If a script starts with indicator(), it can't create Strategy Tester trades or apply trading costs.
These settings have distinct jobs:
| Setting | What it models | Unit you enter | When it applies |
|---|---|---|---|
commission_type | Fee method | Pine commission enum | Each filled order |
commission_value | Fee amount | Depends on the selected method | Each filled order |
slippage | Adverse market-fill offset | Whole ticks | Eligible simulated market and stop fills |
| Limit-order verification | Price movement required before a limit fills | Whole ticks | Limit orders only |
TradingView documents commission and slippage as strategy properties, and its strategy concepts documentation explains the broker emulator assumptions behind historical fills. The strategy declaration reference is the source of truth for supported strategy() arguments.
A commission is charged per filled order, not per completed trade. A normal long entry and its exit create two charged fills. A reversal or partial exit can create more, so always inspect the List of Trades after you change your cost model.
Model slippage in the instrument's actual tick size. With a 0.25 minimum tick,
slippage = 2means a 0.50 adverse price shift. With a 0.01 tick, the same setting means 0.02.
Paste this cost-aware EMA strategy into Pine Editor
This complete Pine Script v6 template has 9/21 EMA crossover entries, 10% equity sizing, a 0.05% fee per filled order, and two ticks of slippage. It also places a 2% protective stop and 4% target from average entry price. Those exit values make the example testable, not universally appropriate.
//@version=6
strategy(
"Cost-Aware EMA Cross",
overlay = true,
initial_capital = 10000,
currency = currency.USD,
default_qty_type = strategy.percent_of_equity,
default_qty_value = 10,
pyramiding = 0,
commission_type = strategy.commission.percent,
commission_value = 0.05,
slippage = 2)
// Signal controls
fastLength = input.int(9, "Fast EMA", minval = 1)
slowLength = input.int(21, "Slow EMA", minval = 2)
allowShorts = input.bool(true, "Allow short trades")
// Exit controls, expressed as a percentage of filled entry price.
stopLossPct = input.float(2.0, "Stop loss (%)", minval = 0.1, step = 0.1) / 100.0
takeProfitPct = input.float(4.0, "Take profit (%)", minval = 0.1, step = 0.1) / 100.0
fastEma = ta.ema(close, fastLength)
slowEma = ta.ema(close, slowLength)
longSignal = ta.crossover(fastEma, slowEma)
shortSignal = ta.crossunder(fastEma, slowEma)
// Entries use the declaration's 10% of equity sizing.
if longSignal
strategy.entry("Long", strategy.long)
if allowShorts and shortSignal
strategy.entry("Short", strategy.short)
// Bracket prices update from the average filled entry price.
longStop = strategy.position_avg_price * (1.0 - stopLossPct)
longTarget = strategy.position_avg_price * (1.0 + takeProfitPct)
shortStop = strategy.position_avg_price * (1.0 + stopLossPct)
shortTarget = strategy.position_avg_price * (1.0 - takeProfitPct)
strategy.exit("Long exit", from_entry = "Long", stop = longStop, limit = longTarget)
strategy.exit("Short exit", from_entry = "Short", stop = shortStop, limit = shortTarget)
plot(fastEma, "Fast EMA", color = color.teal, linewidth = 2)
plot(slowEma, "Slow EMA", color = color.orange, linewidth = 2)
bgcolor(strategy.position_size > 0 ? color.new(color.teal, 92) : strategy.position_size < 0 ? color.new(color.red, 92) : na)
Open TradingView's Pine Editor, paste the script, click Add to chart, and then open Strategy Tester. Keep symbol, timeframe, and test period fixed whenever you compare costs. A changed chart sample makes a before-and-after comparison meaningless.
The key declaration lines are:
commission_type = strategy.commission.percentsays the fee is a percent of filled order value.commission_value = 0.05means 0.05%, or five basis points, for every filled order.slippage = 2gives eligible fills a two-tick adverse offset. Its cash effect changes with tick size and quantity.
The 9/21 pair turns over often enough to make friction visible. For a slower signal baseline, borrow the entry logic from the simple moving average crossover strategy, but don't alter friction assumptions while judging which signal is more cost-sensitive.
Pick the commission type that matches your fee schedule
commission_value has no standalone meaning. Pine interprets it according to commission_type, so choose the mode first.
| Venue fee schedule | Pine setting | Example value | Interpretation |
|---|---|---|---|
| Percentage of order notional | strategy.commission.percent | 0.05 | 0.05% per filled order |
| Flat fee per order | strategy.commission.cash_per_order | 1.00 | $1 per filled order in strategy currency |
| Fee per unit or contract | strategy.commission.cash_per_contract | 2.50 | $2.50 for each filled unit or contract |
The most common configuration error is a decimal-place mistake. With strategy.commission.percent, 0.05 is 0.05%, not 0.0005%. If you intended a 10-basis-point fee, enter 0.10. Spot-check one trade's commission against its order value before accepting a report.
Per-contract pricing needs extra care. A futures contract, forex lot, CFD unit, and crypto unit don't share a quantity definition. Match Pine's simulated quantity to the contract convention your venue bills. For flat cash fees, set the strategy currency so the report uses the denomination you mean to review.
Keep commission mode explicit in code
Don't turn fee mode into an opaque optimization variable. Create separate, named script copies if you need to compare schedules. For example, save EMA Cross - 0.05 percent, EMA Cross - $1 per order, and EMA Cross - $2.50 contract.
Only change these two declaration lines between copies:
commission_type = strategy.commission.cash_per_contract,
commission_value = 2.50,
That preserves entry, exit, chart, and sizing logic. You can then attribute report changes to the fee model instead of wondering which input moved.
Set slippage in ticks, not dollars or percent
Pine's slippage setting is an integer count of minimum price increments. It isn't dollars, percent, points, or pips unless one of those happens to equal the symbol's tick. TradingView lists slippage in ticks in its Strategy Properties guide.
Use this rough price calculation first:
Adverse price movement per filled unit = slippage ticks × syminfo.mintick
If minimum tick is 0.25 and slippage is 2, the modeled adverse move is 0.50 per unit. With a 0.01-tick stock, two ticks is 0.02 per share. The account-currency impact also depends on quantity and, for derivatives, the contract's point value.
A fixed setting is still a simplification. It won't automatically widen for a thin session, a gap, or a news release. Treat it as a scenario assumption. Test a baseline based on normal execution conditions, then run a tougher setting to see whether the strategy depends on unusually favorable fills.
A useful friction ladder is 0, 1, 2, and 4 ticks. Keep the same commission schedule at every rung. If a strategy only works with zero slippage, the report is describing an ideal fill path rather than a tradable one.
Configure limit-order verification separately
The template uses strategy.exit() with both stop and limit prices. These order types should not be treated as having identical fill assumptions.
- A
stop =exit is a protective stop. Model plausible adverse execution with your strategy'sslippagesetting. - A
limit =target is a limit order. Configure Verify price for limit orders in Strategy Settings → Properties if you want price to move a stated number of ticks beyond the limit before historical fill eligibility. - A limit-verification value of 1 is a reasonable starting scenario when you want a bar touch alone to be insufficient. It is not a generic penalty applied to all fills.
Older Pine examples may refer to limit verification as backtest_fill_limits_assumption. Treat that as the name of the broker-emulator assumption, but use the Properties control shown by your current TradingView interface when the declaration parser doesn't accept it. The practical distinction remains the same: verification decides whether a limit order could fill; slippage models an adverse fill offset.
This matters because a historical candle can span both a stop and a target. Cost settings don't reconstruct the bar's intrabar sequence. If your strategy is highly sensitive to that sequence, use lower-timeframe fill tools as a separate test decision. Don't inflate commission or slippage to compensate for an order-path question.
Size the strategy deliberately before judging costs
The template uses:
initial_capital = 10000
default_qty_type = strategy.percent_of_equity
default_qty_value = 10
That directs a new entry to target 10% of current simulated equity, subject to the symbol's quantity rules. It does not mean the strategy risks 10% of the account. Actual trade risk depends on the fill price, stop distance, quantity, and costs.
Change the declaration to 5% equity if you want smaller proportional positions. Use strategy.fixed when you need each test to use the same share or contract count. For a stop-distance-based position-sizing process, calculate order quantity from the cash risk and stop distance rather than treating the default quantity field as risk management.
That distinction becomes more important with volatility-based exits. The ATR trailing-stop strategy in Pine is a useful next build because its stop distance changes as volatility changes. A fixed 10% equity allocation will not hold the same cash risk across every trade in that design.
Check Properties overrides before trusting the report
After adding a strategy, open Settings → Properties. TradingView exposes initial capital, order size, commissions, slippage, and limit-fill verification there. A saved UI setting can override the assumptions you expected from your code, which is useful for scenario testing but easy to forget.
Use this exact checklist:
- Add the strategy and record net profit, total trades, total commission, average trade, and max drawdown.
- Open Settings → Properties and compare initial capital, order size, commission type, commission value, slippage, and Verify price for limit orders against your intended scenario.
- Reset a stale override, or write down the UI value if you intentionally changed it.
- Open Strategy Tester → List of Trades. Confirm that the entry and exit rows show commissions, then inspect several fill prices.
- Change just one field, such as slippage from 1 to 2 ticks, and rerun the comparison without changing EMA periods, date range, or sizing.
Properties are convenient for stress tests. The declaration is better for a reusable baseline because someone who copies your script sees the stated defaults. If a label changes in TradingView, use the official documentation rather than an old screenshot as your reference.
Run a clean before-and-after cost test
Don't enable every realism feature and then guess why the report moved. Run two controlled passes.
Pass A: zero-cost reference
Temporarily set commission_value = 0 and slippage = 0. Keep the 9/21 EMA inputs, 10% equity sizing, date range, and chart unchanged. Record total trades, net profit, gross profit, gross loss, average trade, and max drawdown.
Pass B: fee and slippage scenario
Restore the fee schedule and selected tick setting. Record the same fields. The difference shows the strategy's sensitivity to the modeled frictions. It doesn't forecast future execution, but it reveals whether small gross gains are being consumed by ordinary trading costs.
For definitions of the tester fields you record, read Understanding Backtesting Metrics. Keep the jobs separate: this configuration makes the test assumptions clearer; it doesn't validate a strategy from one historical report.
Common mistakes that create overly clean results
❌ Mistake: Entering 0.0005 for a 0.05% fee. That models 0.0005%, which is one hundredth of the intended five-basis-point cost.
✅ Do this: Write the fee in percent before editing code. Five basis points equals 0.05; ten basis points equals 0.10. Verify one commission figure in List of Trades.
❌ Mistake: Treating slippage = 1 as one dollar. It means one tick, whatever that tick is on the current symbol.
✅ Do this: Check syminfo.mintick. Three ticks on a 0.01-tick stock are 0.03 per share in price movement. Three ticks on a 0.25-tick contract are 0.75 points before contract-value conversion.
❌ Mistake: Using limit verification as all-purpose slippage. It changes whether a limit is deemed fillable, not the price penalty on every order.
✅ Do this: Use strategy slippage for adverse market and stop-fill scenarios. Set Verify price for limit orders only for limit entries and targets.
❌ Mistake: Altering code and Properties values at the same time. You can accidentally compare different fee, capital, quantity, and signal settings in one step.
✅ Do this: Save one named baseline. Test one input at a time and note symbol, timeframe, date range, commission, slippage, quantity model, and limit verification setting.
Pro tips for making the test tougher without making it vague
Audit turnover before adding filters. A 9/21 cross can make enough trades for small friction to dominate. Check how much average trade remains after the 1-, 2-, and 4-tick ladder before you add complexity. If you later test a momentum confirmation, build it separately with the combined RSI and MACD indicator.
Don't double-count spread. Commission is generally a known schedule. Spread and fill deterioration vary. If your fixed slippage setting is intended to stand in for spread plus execution loss, label it that way in your test record rather than adding a separate equivalent penalty later.
Use the trade list as an audit trail. Summary metrics hide individual fills. Spot-check one entry, one stop exit, and one target exit. Confirm that commission appears where expected and that prices behave consistently with the tick setting.
Generating this without writing the code yourself
HorizonAI can generate this Pine Script v6 strategy from a plain-English specification, then you can edit the assumptions in chat. It returns compile-checked code for you to paste into TradingView's Pine Editor. HorizonAI writes the strategy code; it doesn't place or run trades for you.
Build a Pine Script v6 TradingView strategy named "Cost-Aware EMA Cross." Use 9 and 21 EMA crossover entries, optional short trades, initial capital of 10000 USD, 10% of equity per entry, and pyramiding 0. Set commission to 0.05% per filled order and slippage to 2 ticks. Add a 2% stop loss and 4% profit target calculated from average entry price. Plot both EMAs and shade the background teal when long and red when short. Explain which declaration lines control fee type, fee value, slippage, capital, and order size.
Change that same Pine v6 strategy to use
strategy.commission.cash_per_contractwith a commission value of 2.50. Keep the signal and exit logic unchanged, and explain the declaration changes.
HorizonAI can also debug an existing script if a declaration argument or order call fails to compile. Try it free →
FAQs
Does Pine Script charge commission on the entry and exit?
Yes. Commission applies to each filled order. A normal entry and exit therefore usually generate two commission charges, while reversals and partial exits can create more.
Does slippage = 2 mean two cents?
Only for an instrument whose minimum tick is $0.01. Pine reads the value as ticks, so the price movement is 2 × syminfo.mintick per simulated unit.
Can long and short orders use different slippage settings?
Not through the one global slippage argument in strategy(). Use separate documented scenarios if you need to evaluate asymmetric execution conditions.
Why aren't my code settings changing the Strategy Tester result?
Confirm that the script begins with strategy(), then inspect Settings → Properties. A UI override can replace settings you expected the declaration to control.
Final thoughts
A zero-cost result is a signal prototype, not a fill model. Match the commission mode to the actual bill, express slippage in real ticks, and treat limit verification as a separate question.
Rerun the same 1-, 2-, and 4-tick ladder every time you alter the entry logic. It quickly shows whether the apparent improvement came from a better signal or an easier fill assumption.
Related articles
- How to Backtest a Trading Strategy — Build a repeatable process around correctly configured tests.
- How to Backtest Trading Strategies Like a Pro — Avoid test-design errors that distort reports.
- Understanding Backtesting Metrics — Read the report fields used in before-and-after comparisons.
- Pine Script Tutorial for Beginners — Start working with TradingView strategies in the editor.
- How to Code an ATR Trailing Stop Strategy in Pine v6 — Add volatility-aware exits to a Pine strategy.
- Pine Script Repainting: Why It Happens and How to Fix It — Separate signal integrity from fill modeling.
- How to Use Bar Magnifier in a Pine Script v6 Strategy — Improve intrabar fill resolution without changing costs.
- Build a VWAP Mean Reversion Strategy in Pine Script v6 — Apply the same friction model to another strategy type.
Questions about Pine Script strategy commission and slippage? Join our Discord to discuss with other traders!
