How to use fixed-fractional position sizing in TradingView's Strategy Tester

This lesson demonstrates how to use fixed-fractional position sizing in TradingView's strategy tester by modifying your Pine Script strategies to risk a percentage of the account balance on each trade.

Check out my other free lessons!

Source Code

// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © ZenAndTheArtOfTrading
// @version=6
strategy("My strategy", overlay=true, fill_orders_on_standard_ohlc = true)

//! STEP 1: Import my library.
import ZenAndTheArtOfTrading/ZenLibrary/12 as zen

// Allow turning on/off fixed-fractional
bool useFF = input.bool(title="Use Fixed Fractional Position Sizing", defval=true)

// Get required indicator values 
float atrValue = ta.atr(14)
float fastMA = ta.sma(close, 14)
float slowMA = ta.sma(close, 28)
indicatorsReady = not na(atrValue)

// !STEP 2: Calculate long stop loss, price distance, and 1:1 profit target
float longStopTemp = ta.lowest(low, 10) - atrValue 
float longStopDistTemp = math.abs(close - longStopTemp)
float longTargetTemp = close + (longStopDistTemp)
//! STEP 3: Get 1% risk based on long stop loss distance
float longQty = zen.getPositionSize(1, longStopDistTemp)

// Calculate short stop loss, price distance, and 1:1 profit target
float shortStopTemp = ta.highest(high, 10) + atrValue
float shortStopDistTemp = math.abs(close - shortStopTemp)
float shortTargetTemp = close - (shortStopDistTemp)
//! STEP 3: Get 1% risk based on short stop loss distance
float shortQty = zen.getPositionSize(1, shortStopDistTemp)

// These are for the strategy.exit() function's limit order params
var float tradeStop = na 
var float tradeTarget = na

// Detect a long entry and pass in our longQty as position size
longCondition = ta.crossover(fastMA, slowMA) and indicatorsReady
if (longCondition and strategy.position_size == 0)
    tradeStop := longStopTemp 
    tradeTarget := longTargetTemp
    if (useFF)
        strategy.entry("Long", strategy.long, qty=longQty)
    else 
        strategy.entry("Long", strategy.long)

// Detect a short entry and pass in our shortQty as position size
shortCondition = ta.crossunder(fastMA, slowMA) and indicatorsReady
if (shortCondition and strategy.position_size == 0)
    tradeStop := shortStopTemp 
    tradeTarget := shortTargetTemp
    if (useFF)
        strategy.entry("Short", strategy.short, qty=shortQty)
    else 
        strategy.entry("Short", strategy.short)

// Enter/exit trades based on fixed stop loss & take profit
strategy.exit("Long Exit", "Long", stop=tradeStop, limit=tradeTarget)
strategy.exit("Short Exit", "Short", stop=tradeStop, limit=tradeTarget)

// DEBUG: Draw limit orders and strategy indicator values
plot(strategy.position_size != 0 ? tradeStop : na, color=color.red, style=plot.style_linebr)
plot(strategy.position_size != 0 ? tradeTarget : na, color=color.green, style=plot.style_linebr)
plot(fastMA)
plot(slowMA)