Pine Script Monte Carlo

This script demonstrates how to add some basic Monte Carlo simulation code into TradingView strategy scripts for backtesting.

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=5
strategy("TheArtOfTrading.com", overlay=true, calc_on_order_fills=true)

// Import library 
import ZenAndTheArtOfTrading/ZenLibrary/8 as zen

// User inputs 
float SKIP_TRADE_CHANCE = input.float(title="Monte Carlo Skip %", defval=10)
float RANDOM_SPREAD = input.float(title="Random Spread", defval=1)
int MONTE_CARLO_REFRESH = input.int(title="Monte Carlo Refresh", defval=0)

// Prepare monte carlo spread (if input MC spread is zero, we rng will not affect LOs at all)
float monteCarloSpread = zen.toPips(zen.random(0, RANDOM_SPREAD))

// Trade stops & targets 
var float RISK_REWARD = 2
var float tradeTakeProfit = na 
var float tradeStopLoss = na
float atrValue = ta.atr(14)
float stopDistance = atrValue
float takeProfitDistance = atrValue * RISK_REWARD

// Long trades
longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28)) and strategy.position_size == 0
if (longCondition)
    if (not zen.skipTradeMonteCarlo(SKIP_TRADE_CHANCE, true))
        strategy.entry("Trade", strategy.long, comment="Long")

// Short trades
shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28)) and strategy.position_size == 0
if (shortCondition)
    if (not zen.skipTradeMonteCarlo(SKIP_TRADE_CHANCE, true))
        strategy.entry("Trade", strategy.short, comment="Short")

// Set fixed stops & targets 
if (strategy.position_size > 0 and na(tradeStopLoss)) // Long trade
    tradeTakeProfit := strategy.position_avg_price + takeProfitDistance
    tradeStopLoss := strategy.position_avg_price - stopDistance
else if (strategy.position_size < 0 and na(tradeStopLoss)) // Short trade
    tradeTakeProfit := strategy.position_avg_price - takeProfitDistance
    tradeStopLoss := strategy.position_avg_price + stopDistance
else if (strategy.position_size == 0) // No trade
    tradeTakeProfit := na
    tradeStopLoss := na

// Calculate randomized spread in realistic manner (harming outcome)
float randomSpreadSL = 0
float randomSpreadTP = 0

if (strategy.position_size > 0)
    randomSpreadSL := monteCarloSpread
    randomSpreadTP := monteCarloSpread * -1
else if (strategy.position_size < 0)
    randomSpreadSL := monteCarloSpread * -1
    randomSpreadTP := monteCarloSpread

// Exit trades 
strategy.exit("Exit", "Trade", limit=tradeTakeProfit + randomSpreadTP, stop=tradeStopLoss + randomSpreadSL)

// Plots 
plot(ta.sma(close, 14), color=color.blue)
plot(ta.sma(close, 28), color=color.orange)
plot(strategy.position_size != 0 ? tradeTakeProfit : na, color=color.green, style=plot.style_linebr)
plot(strategy.position_size != 0 ? tradeStopLoss : na, color=color.red, style=plot.style_linebr)